Objective-C
使用 @synchronized 类实现锁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| Person *person = [[Person alloc] init];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ @synchronized(person) { [person personA]; [NSThread sleepForTimeInterval:3]; } });
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ @synchronized(person) { [person personB]; } });
|
使用 NSRecursiveLock 类实现锁
递归锁,递归或循环方法时使用此方法实现锁,可避免死锁等问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| Person *person = [[Person alloc] init];
NSRecursiveLock *theLock = [[NSRecursiveLock alloc] init];
static void (^testCode)(int); testCode = ^(int value) { [theLock tryLock]; if (value > 0) { [person personA]; [NSThread sleepForTimeInterval:1]; testCode(value - 1); } [theLock unlock]; };
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ testCode(5); });
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [theLock lock]; [person personB]; [theLock unlock]; });
|
使用 NSConditionLock(条件锁)类实现锁
使用此方法可以指定,只有满足条件的时候才可以解锁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| Person *person = [[Person alloc] init];
NSConditionLock *conditionLock = [[NSConditionLock alloc] init];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [conditionLock lock]; [person personA]; [NSThread sleepForTimeInterval:5]; [conditionLock unlockWithCondition:10]; });
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [conditionLock lockWhenCondition:10]; [person personB]; [conditionLock unlock]; });
|
NSDistributedLock(分布式锁)
在 iOS 中不需要用到,也没有这个方法,因此本文不作介绍,这里写出来只是想让大家知道有这个锁存在。
如果想要学习 NSDistributedLock 的话,你可以创建 MAC OS 的项目自己演练,方法请自行 Google,谢谢
C 语言
使用 pthread_mutex_t 实现锁
注意:必须在头文件导入:#import <pthread.h>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| Person *person = [[Person alloc] init];
__block pthread_mutex_t mutex; pthread_mutex_init(&mutex, NULL);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ pthread_mutex_lock(&mutex); [person personA]; [NSThread sleepForTimeInterval:5]; pthread_mutex_unlock(&mutex); });
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ pthread_mutex_lock(&mutex); [person personB]; pthread_mutex_unlock(&mutex); });
|
使用 GCD 实现“锁”(信号量)
GCD 提供一种信号的机制,使用它我们可以创建“锁”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| Person *person = [[Person alloc] init];
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); [person personA]; [NSThread sleepForTimeInterval:5]; dispatch_semaphore_signal(semaphore); });
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); [person personB]; dispatch_semaphore_signal(semaphore); });
|
我在这里解释一下代码。 dispatch_semaphore_wait
方法是把信号量加 1, dispatch_semaphore_signal
是把信号量减 1。
我们把信号量当作是一个计数器,当计数器是一个非负整数时,所有通过它的线程都应该把这个整数减 1。
如果计数器大于 0,那么则允许访问,并把计数器减 1。如果为 0,则访问被禁止,所有通过它的线程都处于
等待的状态。
使用 POSIX(条件锁)创建锁)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| Person *person = [[Person alloc] init];
__block pthread_mutex_t mutex; pthread_mutex_init(&mutex, NULL);
__block pthread_cond_t cond; pthread_cond_init(&cond, NULL);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ pthread_mutex_lock(&mutex); pthread_cond_wait(&cond, &mutex); [person personA]; pthread_mutex_unlock(&mutex); });
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ pthread_mutex_lock(&mutex); [person personB]; [NSThread sleepForTimeInterval:5]; pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); });
|
效果:程序会首先调用线程 B,在 5 秒后再调用线程 A。因为在线程 A 中创建了等待条件锁,线程 B 有激活锁,只有当线程 B 执行完后会激活线程 A。
pthread_cond_wait
方法为等待条件锁。
pthread_cond_signal
方法为激活一个相同条件的条件锁。
注意:自旋锁 OSSpinLock
已经不再线程安全
参考资料