队列、同步/异步函数、单例、信号量和调度组的底层原理分析
2024-01-18 19:05:50
GCD(Grand Central Dispatch)是 macOS 和 iOS 中线程管理的基石。它提供了一组强大的 API,可用于创建和管理线程、同步和异步任务,以及构建复杂的并发程序。本文将深入剖析 GCD 的底层原理,探讨队列、同步/异步函数、单例、信号量和调度组的工作原理。
队列
创建队列
GCD 队列是任务执行的容器。要创建队列,请使用 dispatch_queue_create
函数。此函数需要两个参数:
- 名称: 唯一标识队列的字符串。
- 属性: 指定队列类型的标志。
队列类型
GCD 提供了各种队列类型,每种类型都有自己独特的特性:
- 并行队列: 并行执行任务,可用于执行独立的任务。
- 串行队列: 串行执行任务,用于按顺序执行依赖的任务。
- 主队列: 应用程序的主线程,用于更新 UI 和处理用户交互。
同步和异步队列
队列还可以分为同步队列和异步队列:
- 同步队列: 在提交新任务之前等待当前任务完成。
- 异步队列: 立即提交新任务,而无需等待当前任务完成。
同步和异步函数
同步函数
同步函数会在当前线程中立即执行,并且在函数返回之前等待结果。例如:
int result = dispatch_sync(my_queue, ^{
// 执行同步任务
return 42;
});
异步函数
异步函数会在后台线程中执行,并且在函数返回后立即继续执行。例如:
dispatch_async(my_queue, ^{
// 执行异步任务
});
GCD 提供了多种用于创建和管理同步和异步函数的函数,例如 dispatch_sync
、dispatch_async
和 dispatch_apply
。
单例
创建单例
单例是全局可访问的对象,只有一个实例。在 GCD 中,可以使用 dispatch_once
函数创建单例:
static void initialize_singleton() {
// 初始化单例
}
void get_singleton() {
static dispatch_once_t once_token;
dispatch_once(&once_token, initialize_singleton);
}
使用单例
一旦单例初始化,就可以通过调用 get_singleton
函数来访问它。
信号量
创建信号量
信号量是一种同步原语,用于限制并发访问资源。要创建信号量,请使用 dispatch_semaphore_create
函数。此函数需要一个参数:
- 值: 初始信号量值。
使用信号量
要使用信号量,请使用 dispatch_semaphore_wait
和 dispatch_semaphore_signal
函数:
dispatch_semaphore_wait
:使当前线程等待信号量值大于 0。dispatch_semaphore_signal
:将信号量值加 1,可能唤醒等待的线程。
调度组
创建调度组
调度组是一种同步原语,用于跟踪一组任务的执行情况。要创建调度组,请使用 dispatch_group_create
函数。
使用调度组
要使用调度组,请使用 dispatch_group_enter
和 dispatch_group_leave
函数:
dispatch_group_enter
:进入调度组。dispatch_group_leave
:离开调度组并通知组中剩余的任务。
当调度组中的所有任务都完成时,可以调用 dispatch_group_wait
函数等待所有任务完成。
结束语
GCD 提供了一套强大的 API,用于管理线程、同步和异步任务,以及构建复杂的并发程序。本文深入分析了 GCD 的底层原理,包括队列、同步/异步函数、单例、信号量和调度组。了解这些原理对于构建高性能、可扩展和可维护的并发应用程序至关重要。