浅谈iOS中的锁的介绍及使用

2020-01-21 02:17:48于海丽

2.4、NSCondition

NSCondition 是一种特殊类型的锁,通过它可以实现不同线程的调度。一个线程被某一个条件所阻塞,直到另一个线程满足该条件从而发送信号给该线程使得该线程可以正确的执行。比如说,你可以开启一个线程下载图片,一个线程处理图片。这样的话,需要处理图片的线程由于没有图片会阻塞,当下载线程下载完成之后,则满足了需要处理图片的线程的需求,这样可以给定一个信号,让处理图片的线程恢复运行。

    NSCondition 的对象实际上作为一个锁和一个线程检查器,锁上之后其它线程也能上锁,而之后可以根据条件决定是否继续运行线程,即线程是否要进入 waiting 状态,如果进入 waiting 状态,当其它线程中的该锁执行 signal 或者 broadcast 方法时,线程被唤醒,继续运行之后的方法。 NSCondition 可以手动控制线程的挂起与唤醒,可以利用这个特性设置依赖。

源码内容:


@interface NSCondition : NSObject <NSLocking> {
@private
  void *_priv;
}

- (void)wait; //挂起线程
- (BOOL)waitUntilDate:(NSDate *)limit; //什么时候挂起线程
- (void)signal; // 唤醒一条挂起线程
- (void)broadcast; //唤醒所有挂起线程

@property (nullable, copy) NSString *name API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));

@end

用法:


- (void)viewDidLoad {
  [super viewDidLoad];

  [self nscondition];
}

- (void)nscondition {
  NSCondition * cjcondition = [NSCondition new];
  
  dispatch_async(dispatch_get_global_queue(0, 0), ^{
    [cjcondition lock];
    NSLog(@"线程1线程加锁");
    [cjcondition wait];
    NSLog(@"线程1线程唤醒");
    [cjcondition unlock];
    NSLog(@"线程1线程解锁");
  });
  
  dispatch_async(dispatch_get_global_queue(0, 0), ^{
    [cjcondition lock];
    NSLog(@"线程2线程加锁");
    if ([cjcondition waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:10]]) {
      NSLog(@"线程2线程唤醒");
      [cjcondition unlock];
      NSLog(@"线程2线程解锁");
    }
  });
  
  dispatch_async(dispatch_get_global_queue(0, 0), ^{
    sleep(2);
    [cjcondition signal];
  });
}

控制台输出:

2017-10-19 17:15:48.410316+0800 Thread-Lock[40011:943638] 线程1线程加锁
2017-10-19 17:15:48.410757+0800 Thread-Lock[40011:943640] 线程2线程加锁
2017-10-19 17:15:50.414288+0800 Thread-Lock[40011:943638] 线程1线程唤醒
2017-10-19 17:15:50.414454+0800 Thread-Lock[40011:943638] 线程1线程解锁


//如果 [cjcondition signal]; 改成 [cjcondition broadcast];
  dispatch_async(dispatch_get_global_queue(0, 0), ^{
    sleep(2);
    [cjcondition broadcast];
  });

控制台输出:

2017-10-19 17:18:08.054109+0800 Thread-Lock[40056:946099] 线程1线程加锁