「这是我参与11月更文挑战的第17天,活动详情查看:2021最后一次更文挑战」
NSConditionLock(条件锁)
NSConditionLock 概念
NSConditionLock
是对 NSCondition
做了一层封装,通过条件变量来控制加锁、解锁,从而达到阻塞线程、唤醒线程的目的
NSConditionLock 常用方法 <遵守 NSLocking
协议>
-
如果没有其他线程加锁,但是该锁内部的
condition
条件不等于传入值,此行以下代码不能加锁,进入等待状态,会阻塞线程。如果锁内部的condition
条件等于传入值,并且没有其他线程加锁,则进⼊代码区。同时设置加锁,其他任何线程都将等待它的代码完成,直⾄它解锁- (void)lockWhenCondition:(NSInteger)condition; 复制代码
-
解锁操作,同时把内部的
condition
条件设置为传入值- (void)unlockWithCondition:(NSInteger)condition; 复制代码
-
尝试加锁,当锁的条件值与传入值相等,则加锁成功,否则失败返回
NO
,不会阻塞线程- (BOOL)tryLockWhenCondition:(NSInteger)condition; 复制代码
-
指定时间前尝试加锁,当锁的条件值与传入值相等,则加锁成功返回
YES
,否则失败返回NO
,到时间前阻塞线程- (BOOL)lockWhenCondition:(NSInteger)condition beforeDate:(NSDate *)limit; 复制代码
NSConditionLock 常用场景
使用 NSConditionLock
能够解决回调顺序的场景
- (void)viewDidLoad{
[super viewDidLoad];
NSConditionLock *lock = [[NSConditionLock alloc] initWithCondition:0];
//线程1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[lock lockWhenCondition:1];
NSLog(@"线程1");
[lock unlock];
});
//线程2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(4);//以保证让线程2的代码后执行
if ([lock tryLockWhenCondition:0]) {
NSLog(@"线程2");
[lock unlockWithCondition:1];
NSLog(@"线程2解锁成功");
} else {
NSLog(@"线程2尝试加锁失败");
}
});
//线程3
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(2);//以保证让线程3的代码后执行
if ([lock tryLockWhenCondition:2]) {
NSLog(@"线程3");
[lock unlock];
NSLog(@"线程3解锁成功");
} else {
NSLog(@"线程3尝试加锁失败");
}
});
}
复制代码
log:
1、初始化 NSConditionLock
对象,并设置 condition
为0
2、当线程1调用 [lock lockWhenCondition:1]
,此刻因为不满足当前条件,所以会进入等待状态,会阻塞线程
3、线程3调用 [lock tryLockWhenCondition:2]
,此刻因为不满足当前条件,但是不会阻塞线程,所以打印出:线程3尝试加锁失败
4、线程2调用 [lock tryLockWhenCondition:0]
,因为当锁的条件值与传入值相等,会输出线程2的打印,打印完成后会调用 [lock unlockWithCondition:1]
,这个时候将条件设置为1,并发送 boradcast
, 此时线程1接收到当前的信号,唤醒线程1并完成线程1的打印