一、GCD 队列底层原理
1.1 队列类型
- 串行队列:一次只执行一个任务。
- 并发队列:可以并发执行多个任务。
- 主队列:主线程的串行队列,用于更新 UI。
1.2 队列背后的线程
- GCD 使用 线程池 管理线程,具体由 libdispatch + pthread 实现。
- 并发队列任务实际是串行调度、并发执行(由系统根据线程池和资源自动调度)。
二、常见 GCD 高级用法
2.1 dispatch_barrier(栅栏函数)
1 2 3 4 5 6 7 8 9 10 11 12 13
| dispatch_queue_t queue = dispatch_queue_create("com.example.queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{ });
dispatch_barrier_async(queue, ^{ });
dispatch_async(queue, ^{ });
|
2.2 dispatch_group(任务组)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| dispatch_group_t group = dispatch_group_create(); dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_group_async(group, queue, ^{ });
dispatch_group_async(group, queue, ^{ });
dispatch_group_notify(group, dispatch_get_main_queue(), ^{ });
|
2.3 dispatch_semaphore(信号量)
1 2 3 4 5 6 7
| dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
dispatch_async(queue, ^{ dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); dispatch_semaphore_signal(semaphore); });
|
三、避免死锁与优雅使用
3.1 死锁示例(主队列同步调用)
1 2 3
| dispatch_sync(dispatch_get_main_queue(), ^{ });
|
3.2 dispatch_once(线程安全的单例初始化)
1 2 3 4
| static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ });
|
四、GCD 优化技巧与实践
4.1 控制最大并发数(结合 semaphore)
1 2 3 4 5 6 7 8
| dispatch_semaphore_t sema = dispatch_semaphore_create(3); for (int i = 0; i < 10; i++) { dispatch_async(queue, ^{ dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); dispatch_semaphore_signal(sema); }); }
|
4.2 使用 QoS(服务质量)
1 2
| dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_CONCURRENT, QOS_CLASS_USER_INITIATED, 0); dispatch_queue_t queue = dispatch_queue_create("com.example.qosqueue", attr);
|
五、和 NSOperation 比较
特性 |
GCD |
NSOperation |
简洁性 |
✅ |
❌(更复杂) |
依赖管理 |
❌ |
✅(operation.addDependency) |
取消任务 |
❌ |
✅(operation.cancel) |
重用性/扩展性 |
❌ |
✅(子类化) |
并发控制(数量) |
借助 semaphore |
✅(maxConcurrentOperationCount) |
GCD 的底层实现原理
Grand Central Dispatch(GCD)是苹果提供的一个多线程并发编程框架,其底层实现原理可以从几个关键的技术点来理解,包括:
一、核心结构与实现基础
1. GCD 基于 libdispatch 实现
GCD 的底层是开源的 libdispatch
库,核心用 C 和 C++ 编写,运行在系统内核之上,封装了线程调度、任务分发、队列管理等功能。
二、任务与队列模型
1. 任务:Block 形式的封装代码(实质是闭包)
每个任务是一个 dispatch_block_t
,本质是封装在结构体中的函数指针和上下文数据。
2. 队列:串行 or 并发
- 串行队列:任务一个个顺序执行。
- 并发队列:任务可同时执行,具体是否并行取决于系统资源。
底层由结构体 dispatch_queue_s
表示,内部包含:
- 队列名称
- 优先级(QoS)
- Target Queue(用于继承行为)
- 队列状态(是否正在执行任务)
- 队列类型(串行/并发)
三、线程调度原理
1. 线程池机制
GCD 不直接创建线程,而是复用一个系统管理的线程池(Managed Thread Pool):
- Apple 使用内核的
pthread
和 kqueue
机制动态创建和调度线程。
- 调用
dispatch_async
等方法时任务进入队列,等待调度器(libdispatch
)判断是否需要从线程池中取线程执行。
2. 结合内核的调度器
- 使用 XNU 内核提供的 workloop(基于
kqueue
)来监视队列变化。
- 利用信号量、原子操作、互斥锁控制任务同步。
四、队列的调度机制
1. dispatch_async / dispatch_sync 的区别
方法 |
调度行为 |
是否阻塞线程 |
dispatch_async |
异步入队 |
否 |
dispatch_sync |
同步执行,当前线程等待任务完成 |
是 |
底层通过:
dispatch_async
:创建任务对象 -> 放入目标队列 -> 唤醒线程池中的线程处理
dispatch_sync
:直接调用任务,并使用 semaphore
阻塞当前线程,直到任务执行完
五、QoS(服务质量)控制
GCD 支持 QoS(Quality of Service)等级,例如:
- userInteractive(最高)
- userInitiated
- default
- utility
- background(最低)
这些优先级通过底层设置线程调度属性,在内核中会影响线程抢占和执行顺序。
六、关键数据结构(源码角度)
1. dispatch_queue_s
(队列结构体)
包含:
1 2 3 4 5 6 7
| struct dispatch_queue_s { ... dispatch_object_t _head; dispatch_object_t _tail; pthread_priority_t _priority; ... };
|
2. dispatch_continuation_s
(封装 block 的任务结构体)
1 2 3 4 5
| struct dispatch_continuation_s { void *dc_func; void *dc_ctxt; ... };
|
七、并发控制:信号量、栅栏、组
dispatch_semaphore
:底层基于 semaphore_t
(Mach 信号量)
dispatch_barrier
:写操作时阻塞其他任务,底层使用任务依赖和标记机制实现
dispatch_group
:通过计数器追踪任务组状态,配合信号量实现通知
总结
GCD 是基于 libdispatch 构建的线程池 + 队列调度框架,其核心优势包括:
- 高效的线程复用
- 简洁的 API 封装(block)
- 动态优先级管理(QoS)
- 底层结合内核机制(如 kqueue 和 pthread)