1-11.【GCD】多个串行队列之间是否存在执行顺序?

3 阅读2分钟

多个串行队列之间不存在天然的执行顺序,它们是相互独立的。只有同一个队列内部的任务才严格按 FIFO(First In, First Out(先进先出)) 顺序执行。

下面详细拆开理解:


1️⃣ 同一串行队列 vs 不同串行队列

单个串行队列

let queue = DispatchQueue(label: "serial")
queue.async { print("A") }
queue.async { print("B") }
  • 保证输出顺序:AB
  • 任何时刻只有一个任务在执行

不同串行队列

let queue1 = DispatchQueue(label: "serial1")
let queue2 = DispatchQueue(label: "serial2")

queue1.async { print("A") }
queue2.async { print("B") }
  • 输出顺序不确定

    • 可能 AB
    • 也可能 BA
  • 原因:

    • 两个队列的 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 或显式同步机制,才能建立队列间的顺序关系。