1、NSCondition
NSCondition是对mutex和cond的封装,可以通过 GNUstep源码 中的NSLock.m查看:
@interface NSCondition : NSObject <NSLocking> {gs_cond_t _condition;gs_mutex_t _mutex;NSString *_name;}
有如下API:
- (void)NSConditionAPI {// 初始化NSCondition *condition = [[NSCondition alloc] init];// 加锁[condition lock];// 解锁[condition unlock];// 等待[condition wait];// 在设定时间钱等待[condition waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];// 发送信号[condition signal];// 发送广播[condition broadcast];}
使用方式和mutex+cond相同:
// 线程一:删除数组元素- (void)__remove {[self.cond lock];NSLog(@"线程1: 【加锁】");if (self.arr.count == 0) {NSLog(@"线程1: 开始等待(条件不成立,开始休眠,并【解锁】)");[self.cond wait];NSLog(@"线程1: 结束等待(接收到条件成立,【加锁】并执行后续操作)");}NSLog(@"线程1: 删除元素");[self.arr removeLastObject];NSLog(@"线程1:【解锁】");[self.cond unlock];}// 线程二:添加数组元素- (void)__add {[self.cond lock];NSLog(@"线程2: 【加锁】");NSLog(@"线程2: 添加元素");[self.arr addObject:@"1"];NSLog(@"线程2: 通知线程1条件成立");[self.cond signal];NSLog(@"线程2: 【解锁】");[self.cond unlock];}
*关于cond先调用signal还是先调用unlock问题: 如果先调用signal,线程2还在加锁中,wait方法不会给线程1马上加锁,会等待线程2解锁后在加锁并处理后续操作。 如果先调用unlock,线程2已经解锁,再调用singal,wait方法会马上解锁并处理后续操作。
2、NSConditionLock
NSConditionLock是对NSCondition的进一步封装,可以设置具体的条件值,让线程间实现依赖关系。
可以通过 GNUstep源码 中的NSLock.m查看NSConditionLock底层实现:
@interface NSConditionLock : NSObject <NSLocking>{NSCondition *_condition;int _condition_value;NSString *_name;}
*_condition_value默认值为0
// 加锁方法- (void) lockWhenCondition: (NSInteger)value{[_condition lock];while (value != _condition_value){[_condition wait];}}
*通过加锁源码可知,当条件不成立时,也是利用while循环进行等待,所以也可以将NSConditionLock理解成一个“自旋锁”
有如下API:
- (void)NSConditionLockAPI {// 初始化,设置初始条件,默认为0NSConditionLock *conditionLock = [[NSConditionLock alloc] initWithCondition:1];// 加锁[conditionLock lock];// 解锁[conditionLock unlock];// 指定条件时加锁,不然就等待[conditionLock lockWhenCondition:1];// 解锁并更新条件[conditionLock unlockWithCondition:1];}
应用举例,让三条线程依次执行:
- (void)__one {[self.conditionLock lockWhenCondition:1];NSLog(@"%s", __func__);sleep(1);[self.conditionLock unlockWithCondition:2];}- (void)__two {[self.conditionLock lockWhenCondition:2];NSLog(@"%s", __func__);sleep(1);[self.conditionLock unlockWithCondition:3];}- (void)__three {[self.conditionLock lockWhenCondition:3];NSLog(@"%s", __func__);sleep(1);[self.conditionLock unlock];}
~: -[NSConditionLockDemo __one]~: -[NSConditionLockDemo __two]~: -[NSConditionLockDemo __three]
