# 31.锁｜NSConditionLock

## 一、 NSConditionLock

先来看一个面试题，下面代码输出的顺序会是什么样。

```swift
let conditionLock = NSConditionLock(condition: 2)
let queue1 = DispatchQueue.global(qos: .unspecified)
let queue2 = DispatchQueue.global(qos: .background)
let queue3 = DispatchQueue.global(qos: .default)

queue1.async {
    conditionLock.lock(whenCondition: 1)
    print("1")
    conditionLock.unlock(withCondition: 0)
}

queue2.async {
    conditionLock.lock(whenCondition: 2)
    print("2")
    conditionLock.unlock(withCondition: 1)
}

queue3.async {
    conditionLock.lock()
    print("3")
    conditionLock.unlock()
}
```

### 1.1 API 简单介绍

相信很多同学和我一样没怎么用过这个锁，对着几个API也是蒙的。下面就先介绍一下这些API吧。

* lock(whenCondition:)
  * 在锁定操作成功之前，接收者的条件必须等于 `Condition` 。 这个方法会阻塞线程的执行，直到可以获取到锁，即满足 `Condition` 。
* unlock(withCondition:)
  * 解锁并设置 `Condition`
* lock
  * 如果没有其他线程获得锁那它能执⾏此⾏以下代码，如果已经有其他线程获得锁，则等待，直⾄其他线程解锁
* unlock
  * 解锁

### 1.2 分析

`queue1` 、 `queue2` 、 `queue3`根据优先级从高到低： `queue1` > `queue3` > `queue2`

如果不看锁的部分，执行的顺序大概率是 1 3 2。但是这里有锁，所以这里的优先级是一个迷惑项。

***执行步骤如下：***

* condition = 2
  * 满足 2 的进入条件，但是 `queue3` 优先级更高，所以 3 大概率优先输出
  * 3 输出
  * condition 不变
* condition 满足 2 的条件
  * 可以执行 2
  * 2 输出
  * 解锁 condition = 1
* condition 满足 1 的条件
  * 可以执行 1
  * 1 输出
  * 解锁 condition = 0

![2](https://4193904735-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MI8JgbGh3U6X_oedqkm%2Fsync%2F6df9e53d41e016a11d631e27d55f697e9d14d600.png?generation=1631616667568227\&alt=media)

## 参考

* [Swift-Foundation可以查看相关锁的源码](https://github.com/apple/swift-corelibs-foundation)
* [Threading Programming Guide](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Multithreading/Introduction/Introduction.html#//apple_ref/doc/uid/10000057i-CH1-SW1)
