1、NSCondition

NSCondition是对mutex和cond的封装,可以通过 GNUstep源码 中的NSLock.m查看:

  1. @interface NSCondition : NSObject <NSLocking> {
  2. gs_cond_t _condition;
  3. gs_mutex_t _mutex;
  4. NSString *_name;
  5. }

有如下API:

  1. - (void)NSConditionAPI {
  2. // 初始化
  3. NSCondition *condition = [[NSCondition alloc] init];
  4. // 加锁
  5. [condition lock];
  6. // 解锁
  7. [condition unlock];
  8. // 等待
  9. [condition wait];
  10. // 在设定时间钱等待
  11. [condition waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
  12. // 发送信号
  13. [condition signal];
  14. // 发送广播
  15. [condition broadcast];
  16. }

使用方式和mutex+cond相同:

  1. // 线程一:删除数组元素
  2. - (void)__remove {
  3. [self.cond lock];
  4. NSLog(@"线程1: 【加锁】");
  5. if (self.arr.count == 0) {
  6. NSLog(@"线程1: 开始等待(条件不成立,开始休眠,并【解锁】)");
  7. [self.cond wait];
  8. NSLog(@"线程1: 结束等待(接收到条件成立,【加锁】并执行后续操作)");
  9. }
  10. NSLog(@"线程1: 删除元素");
  11. [self.arr removeLastObject];
  12. NSLog(@"线程1:【解锁】");
  13. [self.cond unlock];
  14. }
  15. // 线程二:添加数组元素
  16. - (void)__add {
  17. [self.cond lock];
  18. NSLog(@"线程2: 【加锁】");
  19. NSLog(@"线程2: 添加元素");
  20. [self.arr addObject:@"1"];
  21. NSLog(@"线程2: 通知线程1条件成立");
  22. [self.cond signal];
  23. NSLog(@"线程2: 【解锁】");
  24. [self.cond unlock];
  25. }

*关于cond先调用signal还是先调用unlock问题: 如果先调用signal,线程2还在加锁中,wait方法不会给线程1马上加锁,会等待线程2解锁后在加锁并处理后续操作。 如果先调用unlock,线程2已经解锁,再调用singal,wait方法会马上解锁并处理后续操作。

2、NSConditionLock

NSConditionLock是对NSCondition的进一步封装,可以设置具体的条件值,让线程间实现依赖关系。
可以通过 GNUstep源码 中的NSLock.m查看NSConditionLock底层实现:

  1. @interface NSConditionLock : NSObject <NSLocking>
  2. {
  3. NSCondition *_condition;
  4. int _condition_value;
  5. NSString *_name;
  6. }

*_condition_value默认值为0

  1. // 加锁方法
  2. - (void) lockWhenCondition: (NSInteger)value
  3. {
  4. [_condition lock];
  5. while (value != _condition_value)
  6. {
  7. [_condition wait];
  8. }
  9. }

*通过加锁源码可知,当条件不成立时,也是利用while循环进行等待,所以也可以将NSConditionLock理解成一个“自旋锁”

有如下API:

  1. - (void)NSConditionLockAPI {
  2. // 初始化,设置初始条件,默认为0
  3. NSConditionLock *conditionLock = [[NSConditionLock alloc] initWithCondition:1];
  4. // 加锁
  5. [conditionLock lock];
  6. // 解锁
  7. [conditionLock unlock];
  8. // 指定条件时加锁,不然就等待
  9. [conditionLock lockWhenCondition:1];
  10. // 解锁并更新条件
  11. [conditionLock unlockWithCondition:1];
  12. }

应用举例,让三条线程依次执行:

  1. - (void)__one {
  2. [self.conditionLock lockWhenCondition:1];
  3. NSLog(@"%s", __func__);
  4. sleep(1);
  5. [self.conditionLock unlockWithCondition:2];
  6. }
  7. - (void)__two {
  8. [self.conditionLock lockWhenCondition:2];
  9. NSLog(@"%s", __func__);
  10. sleep(1);
  11. [self.conditionLock unlockWithCondition:3];
  12. }
  13. - (void)__three {
  14. [self.conditionLock lockWhenCondition:3];
  15. NSLog(@"%s", __func__);
  16. sleep(1);
  17. [self.conditionLock unlock];
  18. }
  1. ~: -[NSConditionLockDemo __one]
  2. ~: -[NSConditionLockDemo __two]
  3. ~: -[NSConditionLockDemo __three]