1-6.【GCD】自定义队列在底层是如何映射到全局队列的?

1 阅读3分钟

自定义队列本身不拥有线程;它们通过 target queue 机制,最终把任务“汇流”到某个全局并发队列(按 QoS)上执行。

下面我们从 结构 → 映射路径 → 调度细节 → 常见误解 一层层拆。


1️⃣ 核心模型:Queue ≠ Thread(再强调一次)

在 GCD 里:

  • 队列(DispatchQueue)
    👉 任务的组织和调度规则
  • 线程(worker thread)
    👉 真正执行任务的资源

👉 自定义队列永远不直接绑定线程


2️⃣ 自定义队列创建时发生了什么?

let queue = DispatchQueue(
    label: "com.example.myqueue",
    qos: .utility,
    attributes: [.concurrent]
)

你得到的是一个:

  • 有自己 FIFO / 并发规则的 逻辑队列
  • 没有线程
  • 没有独立线程池

3️⃣ 真正关键的机制:target queue

每一个 dispatch queue 都有一个 target queue

你可以显式指定:

queue.setTarget(queue: DispatchQueue.global(qos: .utility))

但即使你不写:

系统也会自动帮你设

默认 target 规则是:

队列类型默认 target
main queuemain thread / RunLoop
global queueroot queue(系统内部)
自定义 queue对应 QoS 的 global queue

4️⃣ 调度路径(重点流程)

当你执行:

queue.async {
    work()
}

真实发生的是:

你的自定义 queue
   ↓(保持自己的串行 / 并发语义)
target queue(global queue, by QoS)
   ↓
GCD 调度器
   ↓
共享线程池(worker threads)
   ↓
执行 block

👉 自定义队列只负责:

  • 任务顺序
  • barrier
  • 串行 / 并发约束

👉 全局队列负责:

  • 线程选择
  • QoS 调度
  • CPU 分配

5️⃣ 串行队列是如何“跑在并发队列上”的?

这点很容易让人迷糊。

let serial = DispatchQueue(label: "serial")

虽然:

  • serial queue 自己是 串行的
  • 但它的 target 是 并发的 global queue

为什么还能串行?

原因是:

串行语义是在“队列层”保证的,不是在“线程层”

GCD 保证:

  • 同一时间
  • serial queue 只会向 target queue 提交 一个 block

即使 target 是并发的:

  • 永远只会有一个来自该 serial queue 的任务在执行

6️⃣ 并发自定义队列又是如何工作的?

let concurrent = DispatchQueue(
    label: "concurrent",
    attributes: .concurrent
)

特点:

  • 并发规则由 这个队列自己管理
  • 多个 block 可以同时被提交给 target queue
  • target queue(global)负责并行执行

7️⃣ barrier 为什么只能用于自定义并发队列?

queue.async(flags: .barrier) {
    criticalSection()
}

原因很直白:

  • barrier 是 队列内部的语义

  • global queue 是:

    • 共享的
    • 多来源的
  • GCD 无法也不允许:

    • 为“全局公共队列”插入独占屏障

👉 所以:

barrier 只能作用在你“拥有”的那一层队列


8️⃣ QoS 是如何一路传下去的?

  • 自定义队列有自己的 QoS

  • 提交的 block 继承:

    • queue QoS
    • 或 caller QoS(取更高)
  • 最终:

    • 映射到 target global queue
    • 再映射到线程优先级

👉 QoS 是任务属性,不是队列绑定线程。


9️⃣ 一个容易忽略但很重要的点

setTarget(queue:) 可以改变的不只是 QoS

你可以:

queue.setTarget(queue: someSerialQueue)

结果是:

  • 多个队列“汇流”到一个串行队列

  • 从而实现:

    • 资源限流
    • 顺序控制
    • 自定义调度树

这就是 GCD 的“队列树(queue hierarchy)”设计


🔚 一句话终极总结

自定义队列通过 target queue 机制映射到对应 QoS 的全局并发队列执行;它们只定义任务的组织与同步语义,而线程管理与调度完全由全局队列和系统线程池负责。