# 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](/files/-MjYvcBm2-6YYQ-OvVoC)

## 参考

* [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)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ryukiedev.gitbook.io/wiki/ios/di-ceng/31.-suo-nsconditionlock.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
