作为一名多年的iOS开发者,说实话iOS中用到的锁确实不常用,但是也很有用,今天我们来总结一下常用的锁。
1.NSLock
NSLock属于互斥锁,一般只是用于简单的逻辑中,不能多次使用lock,不然会造成死锁。示例代码:
//创建锁
_myLock = [[NSLock alloc] init];
[self testLock];
-(void)testLock {
//上锁
[_mylock lock];
nslog(@"锁了。。。");
//解锁
[_mylock unlock];
}
2.@synchronized
@synchronized属于互斥锁,它跟nslock差不多,但是性能比较差,一般不会去使用它。示例代码:
[self testLock];
-(void)testLock {
@synchronized(self){
nslog(@"锁了。。。");
}
}
3.NSRecursiveLock
NSRecursiveLock属于递归锁,它跟NSLock的区别就在于,NSLock不能多次被lock,但是NSRecursiveLock却可以,但是前提必须是lock和unlock要对应起来,才能真正被释放。示例代码:
//创建锁
_rsLock = [[NSRecursiveLock alloc] init];
//线程1
dispatch_async(self.concurrentQueue, ^{
static void(^TestMethod)(int);
TestMethod = ^(int value)
{
[_rsLock lock];
if (value > 0)
{
[NSThread sleepForTimeInterval:1];
TestMethod(value--);
}
[_rsLock unlock];
};
TestMethod(5);
});
4.NSConditionLock 条件锁
先看示例代码:
//主线程中
NSConditionLock *theLock = [[NSConditionLock alloc] init];
//线程1
dispatch_async(self.concurrentQueue, ^{
for (int i=0;i<=3;i++)
{
[theLock lock];
NSLog(@"thread1:%d",i);
sleep(1);
[theLock unlockWithCondition:i];
}
});
//线程2
dispatch_async(self.concurrentQueue, ^{
[theLock lockWhenCondition:2];
NSLog(@"thread2");
[theLock unlock];
});
输出结果是:thread1:0 thread1:1 thread1:2 thread3 thread1:3
在线程1中的加锁使用了lock,是不需要条件的,所以顺利的就锁住了。
unlockWithCondition在开锁的同时设置了一个整型的条件 2 。线程2则需要一把被标识为2的钥匙,所以当线程1循环到 i = 2 时,线程2的任务才执行。
NSConditionLock也跟其它的锁一样,是需要lock与unlock对应的,只是lock,lockWhenCondition:与unlock,unlockWithCondition:是可以随意组合的,当然这是与你的需求相关的。
5.dispatch_semaphore 信号量实现加锁(GCD)
信号量我们代码中用的都比较多,严格意义上讲,信号量并不是锁,只不过它可以实现锁的功能。示例代码:
// 创建信号量
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
//线程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"任务1");
sleep(10);
dispatch_semaphore_signal(semaphore);
});
//线程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(1);
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"任务2");
dispatch_semaphore_signal(semaphore);
});