NSLock
nslock是互斥锁,非递归所,连续加锁大于等于两次[self.lock lock]会造成死锁
@synchronized
@synchronized 互斥锁(当中的递归锁)跟(NSLock, 更准确的说法应该是递归锁NSRecursiveLock)类似:它可以防止不同的线程同时执行同一段代码。但在某些情况下,相比于使用 NSLock 创建锁对象、加锁和解锁来说,@synchronized 用着更方便,可读性更高, 自然效率会比较低。
只有一个线程
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(self) {
sleep(2);
NSLog(@"线程1");
}
sleep(1);
NSLog(@"线程1解锁成功");
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(self) {
NSLog(@"线程2");
}
});
打印 线程1---->线程2----->线程1解锁成功
@synchronized(object) 指令使用的 object 为该锁的唯一标识,只有当标识相同时,才满足互斥,所以如果线程 2 中的
@synchronized(self) 改为@synchronized(self.view),则线程2就不会被阻塞
@synchronized 指令实现锁的优点就是我们不需要在代码中显式的创建锁对象,便可以实现锁的机制,但作为一种预防措施,
@synchronized 块会隐式的添加一个异常处理例程来保护代码,该处理例程会在异常抛出的时候自动的释放互斥锁。
如果在 @sychronized(object){} 内部 object 被释放或被设为 nil,从测试的结果来看,的确没有问题,但如果 object 一开始就是
nil,则失去了锁的功能。但 @synchronized([NSNull null]) 是完全可以的。
递归锁: 同一个线程可以重复的加锁而不会导致死锁(互斥锁: 同一个线程重复加锁会导致死锁) ,加的递归锁全部执行完后 才会把资源让给别的线程。不同的线程要求加锁会陷入等待.
传入的object必须是有地址的指针的,才能起到加锁效果,如果传入的对象释放了nil就起不到加锁的作用。
GCD信号量 dispatch_semaphore_create(1) 赋值为1就代表锁
信号量置为1 每次都只有一个线程在执行
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//任务1
dispatch_async(queue, ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"run task 1");
sleep(1);
NSLog(@"complete task 1");
dispatch_semaphore_signal(semaphore);
});
//任务2
dispatch_async(queue, ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"run task 2");
sleep(1);
NSLog(@"complete task 2");
dispatch_semaphore_signal(semaphore);
});
//任务3
dispatch_async(queue, ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"run task 3");
sleep(1);
NSLog(@"complete task 3");
dispatch_semaphore_signal(semaphore);
});