多个串行队列之间不存在天然的执行顺序,它们是相互独立的。只有同一个队列内部的任务才严格按 FIFO(First In, First Out(先进先出)) 顺序执行。
下面详细拆开理解:
1️⃣ 同一串行队列 vs 不同串行队列
单个串行队列
let queue = DispatchQueue(label: "serial")
queue.async { print("A") }
queue.async { print("B") }
- 保证输出顺序:
A→B - 任何时刻只有一个任务在执行
不同串行队列
let queue1 = DispatchQueue(label: "serial1")
let queue2 = DispatchQueue(label: "serial2")
queue1.async { print("A") }
queue2.async { print("B") }
-
输出顺序不确定
- 可能
A→B - 也可能
B→A
- 可能
-
原因:
- 两个队列的 target queue 可能是全局并发队列
- GCD 会把它们分配给不同的线程
- 系统调度、线程池状态、QoS 都会影响先后顺序
2️⃣ 串行队列之间建立顺序的方式
如果你想让多个串行队列“有顺序”,有两种方法:
方法 1:通过 target queue 汇流到同一个队列
let serial1 = DispatchQueue(label: "serial1")
let serial2 = DispatchQueue(label: "serial2")
let mainSerial = DispatchQueue(label: "mainSerial")
serial1.setTarget(queue: mainSerial)
serial2.setTarget(queue: mainSerial)
-
结果:
- serial1 和 serial2 的任务最终按提交顺序在 mainSerial 上执行
-
原理:
- GCD 的 queue hierarchy
- target queue 决定顺序屏障
方法 2:使用依赖关系或 semaphore / barrier
queue2.async {
semaphore.wait()
print("B")
semaphore.signal()
}
queue1.async {
print("A")
semaphore.signal()
}
- 通过同步机制强制顺序
- 不依赖 GCD 内部调度
3️⃣ 本质原因
- 串行队列只控制自身内部顺序
- 不同队列之间没有共享状态
- 物理执行线程可能不同,调度完全独立
- GCD 保证的只是 队列内部互斥和顺序一致性
4️⃣ 特别注意:QoS 和 target queue 会影响实际执行顺序
-
高 QoS 的任务可能先执行低 QoS 队列任务
-
如果两个串行队列 target 相同:
- 先提交的任务先执行
-
如果 target 不同:
- 完全由线程池和系统调度决定
5️⃣ 一句话总结(面试友好)
多个串行队列之间没有天然顺序,它们是相互独立的;只有通过共享 target queue 或显式同步机制,才能建立队列间的顺序关系。