- NSRecursiveLock递归锁
所谓递归锁,就是在同一线程上该锁是可重入的,它对于不同线程相当于普通的互斥锁。NSRecursiveLock类定义的锁可以在同一线程多次lock,而不会造成死锁。递归锁会跟踪它被多少次lock。每次成功的lock都必须平衡调用unlock操作。只有所有的锁住和解锁操作都平衡的时候,锁才真正被释放给其他线程获得。
NSRecursiveLock *lock = [[NSRecursiveLock alloc] init];
//开一个线程
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
static void (^RecursiveMethod)(int);
RecursiveMethod = ^(int value) {
[lock lock]; //启动递归锁
if (value > 0) {
NSLog(@"value = %d", value);
sleep(2);
RecursiveMethod(value - 1);
}
[lock unlock]; //关闭递归锁
};
RecursiveMethod(5);
});
//再开一个线程dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(2);
//判断当前锁的状态
BOOL flag = [lock lockBeforeDate:[NSDate dateWithTimeIntervalSinceNow:1]];
if (flag) {
NSLog(@"lock before date");
[lock unlock];
} else {
NSLog(@"fail to lock before date");
}
});
代码分析:第一个异步dispatch创建了一个新的线程,并加入了递归锁,此时,在第二个异步dispatch创建的新线程中,判断当前的递归锁的状态。
2. NSConditionLock条件锁
普通的互斥锁和递归锁都只考虑锁和解锁的问题,这样的锁无法满足多线程对访问共享资源的各种需求。因此,条件锁(NSConditionLock)的出现可以解决多线程技术中需要满足特定条件才能解开某些锁的场景。
//主线程中
NSConditionLock *conditionLock = [[NSConditionLock alloc] init];
//异步线程1 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for (int i=0;i<=2;i++)
{
//创建一个不需要条件的锁
[conditionLock lock];
NSLog(@"thread1:%d",i);
sleep(2);
[conditionLock unlockWithCondition:i];
}
});
//异步线程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//设置一个条件锁,需要对应的unlockWithCondition:2才能解开
[conditionLock lockWhenCondition:2];
NSLog(@"thread2");
[conditionLock unlock];
});
代码分析:异步线程1创建了一个没有开锁条件的条件锁,而异步线程2并发的创建了一个开锁条件为2的条件锁,当线程1中的循环变量i=2时,线程2中的条件锁被解开。
3. NSDistributedLock分布式锁
对于多个进程或多个程序之间需要构建互斥的场景时,使用上述多线程间的锁就无法满足需求。此时,需要使用到分布式锁。分布式锁是通过文件系统实现的,它不继承自NSLock,因而也没有实现lock方法,但它提供了tryLock,unlock,breakLock等方法,如果需要lock,则必须自己实现一个trylock的轮询。
应用A:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//进程间互斥所用的锁
NSDistributedLock *lock = [[NSDistributedLock alloc] initWithPath:@"/Users/mac/Desktop/earning__"];
[lock breakLock];
[lock tryLock];
sleep(10);
[lock unlock];
NSLog(@"appA: OK");
});
应用B:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSDistributedLock *lock = [[NSDistributedLock alloc] initWithPath:@"/Users/mac/Desktop/earning__"];
while (![lock tryLock]) {
NSLog(@"appB: waiting");
sleep(1);
}
[lock unlock];
NSLog(@"appB: OK");
});
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-03 22:25:13