1-21.【GCD】DispatchSource 的事件处理和队列调度关系?

1 阅读2分钟

1️⃣ 核心结论

DispatchSource 的事件处理 block 并不是直接在内核线程执行的,而是通过 GCD 队列异步派发,事件处理和队列调度紧密耦合:队列决定事件处理执行的线程、顺序和并发性。

换句话说:

  • 内核检测到事件 → 通知 GCD → GCD 将事件处理 block 派发到指定队列
  • 队列类型(串行 / 并发)直接影响事件处理执行方式

2️⃣ 队列对事件处理的影响

2.1 串行队列

let queue = DispatchQueue(label: "serialQueue")
let source = DispatchSource.makeReadSource(fileDescriptor: fd, queue: queue)
source.setEventHandler {
    print("事件处理")
}
source.resume()
  • 特点

    • 事件处理在 串行队列上顺序执行
    • 同一时间只有一个事件处理 block 执行
    • 多个事件同时触发 → 丢到队列尾部顺序执行

✅ 优势:顺序性、互斥保证


2.2 并发队列

let queue = DispatchQueue(label: "concurrentQueue", attributes: .concurrent)
let source = DispatchSource.makeReadSource(fileDescriptor: fd, queue: queue)
source.setEventHandler {
    print("事件处理")
}
source.resume()
  • 特点

    • 事件处理可以同时在多个线程上执行(并发)
    • 队列会调度多个事件处理 block 并行执行
    • 事件处理的顺序不保证

✅ 优势:高吞吐量,适合读多写少或高并发场景


3️⃣ 队列调度流程示意

[内核事件触发][内核通知 GCD][DispatchSource 捕获事件][将事件处理 block 派发到目标队列][队列调度 block 执行]
  • 队列类型决定 block 执行方式

    • 串行队列 → 队列内部串行执行
    • 并发队列 → 队列内部并发执行
  • 线程选择由队列管理

    • GCD 可以复用现有线程,也可以从线程池取线程
    • 不会为每个事件 block 新建线程

4️⃣ 队列与事件处理关系要点

  1. 队列决定执行线程

    • 绑定串行队列 → 独占顺序执行
    • 绑定并发队列 → 多线程并行执行
  2. 队列决定顺序和并发性

    • 串行队列保证 FIFO 顺序
    • 并发队列可同时执行多个事件 block
  3. GCD 提供异步调度

    • 内核通知事件 → 不阻塞内核
    • 队列异步执行 → 不阻塞触发线程
  4. 可与 barrier / sync / async 配合

    • 可以在串行或并发队列中使用 barrier 保证写操作独占
    • DispatchSource 事件 block 是普通 GCD block,可与其他任务组合调度

5️⃣ 总结一句话

DispatchSource 的事件处理依赖队列调度:内核检测事件 → 通知 GCD → 队列派发 block → 队列管理线程、顺序和并发性。队列类型决定了事件处理是串行还是并发执行。