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

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

用法:


- (void)viewDidLoad {
  [super viewDidLoad];

  [self nsconditionlock];
}

- (void)nsconditionlock {
  NSConditionLock * cjlock = [[NSConditionLock alloc] initWithCondition:0];
  
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [cjlock lock];
    NSLog(@"线程1加锁成功");
    sleep(1);
    [cjlock unlock];
    NSLog(@"线程1解锁成功");
  });
  
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    sleep(1);
    [cjlock lockWhenCondition:1];
    NSLog(@"线程2加锁成功");
    [cjlock unlock];
    NSLog(@"线程2解锁成功");
  });
  
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    sleep(2);
    if ([cjlock tryLockWhenCondition:0]) {
      NSLog(@"线程3加锁成功");
      sleep(2);
      [cjlock unlockWithCondition:2];
      NSLog(@"线程3解锁成功");
    } else {
      NSLog(@"线程3尝试加锁失败");
    }
  });
  
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    if ([cjlock lockWhenCondition:2 beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]]) {
      NSLog(@"线程4加锁成功");
      [cjlock unlockWithCondition:1];
      NSLog(@"线程4解锁成功");
    } else {
      NSLog(@"线程4尝试加锁失败");
    }
  });
}

控制台输出:

2017-10-19 15:09:44.010992+0800 Thread-Lock[39230:853946] 线程1加锁成功
2017-10-19 15:09:45.012045+0800 Thread-Lock[39230:853946] 线程1解锁成功
2017-10-19 15:09:46.012692+0800 Thread-Lock[39230:853947] 线程3加锁成功
2017-10-19 15:09:48.016536+0800 Thread-Lock[39230:853947] 线程3解锁成功
2017-10-19 15:09:48.016564+0800 Thread-Lock[39230:853944] 线程4加锁成功
2017-10-19 15:09:48.017039+0800 Thread-Lock[39230:853944] 线程4解锁成功
2017-10-19 15:09:48.017040+0800 Thread-Lock[39230:853945] 线程2加锁成功
2017-10-19 15:09:48.017215+0800 Thread-Lock[39230:853945] 线程2解锁成功

由以上内容总结:

    在线程 1 解锁成功之后,线程 2 并没有加锁成功,而是继续等了 1 秒之后线程 3 加锁成功,这是因为线程 2 的加锁条件不满足,初始化时候的 condition 参数为 0,而线程 2 加锁条件是 condition 为 1,所以线程 2 加锁失败。 lockWhenCondition 与 lock 方法类似,加锁失败会阻塞线程,所以线程 2 会被阻塞着。 tryLockWhenCondition: 方法就算条件不满足,也会返回 NO,不会阻塞当前线程。 lockWhenCondition:beforeDate:方法会在约定的时间内一直等待 condition 变为 2,并阻塞当前线程,直到超时后返回 NO。 锁定和解锁的调用可以随意组合,也就是说 lock、lockWhenCondition:与unlock、unlockWithCondition: 是可以按照自己的需求随意组合的。