GCD前戏 -- 相关概念
什么是 GCD
GCD 全称 Grand Central Dispatch,由 C 语言写成的一个库,是苹果公司为多核的并行运算提出的一个解决方案。
- 任务采用 block 封装(无参数无返回值)
- 自动管理线程的生命周期(创建线程、调度任务、销毁线程)
- 只需告诉 GCD 执行的任务(block)以及类型(同步/异步),无需编写任何线程管理代码
苹果对 GCD 源码进行了开源:libdispatch
进程
- 一个应用对应一个进程,进程是应用运行的载体
- 进程之间相互独立运行在专用且受保护的内存空间
- 进程的名称默认就是应用名称
iOS 中的应用都是单进程,不允许通过代码创建新的进程(单进程 & 多线程)
线程
线程(Thread)有时亦被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID、当前指令指针、寄存器集合和堆栈组成。
- 一个进程中至少有一条线程
- 线程之间共享进程的数据
任务
GCD 中的任务主要是以 block 形式进行封装(无参数无返回值),任务添加到队列(串行队列/并发队列)后,由线程进行执行。
除了 block 形式外,GCD 还允许通过传递函数地址(dispatch_function_t)的方式来指定需要执行的任务,这种方式的接口函数有一个特点,基本都是以 _f
结尾的,比如:dispatch_source_set_event_handler_f
。
typedef void (*dispatch_function_t)(void *_Nullable); |
队列
队列分为2种:
- DISPATCH_QUEUE_SERIAL(串行队列)
- DISPATCH_QUEUE_CONCURRENT(并发队列)
系统为我们提供了两个全局队列:
- 全局主队列,通过
dispatch_get_main_queue()
获取- 属于串行队列
- 绑定在主线程(UI线程)上,所以一般用于更新UI
- 在调用
main()
函数之前自动创建 - 如果和
dispatch_sync
一起使用容易导致死锁
- 全局并发队列,通过
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
获取
自定义队列(除系统提供的队列外)通过 dispatch_queue_create
创建,在创建时通过传递 DISPATCH_QUEUE_SERIAL
/DISPATCH_QUEUE_CONCURRENT
来确认队列的类型。
dispatch_queue_t serial_queue = dispatch_queue_create("com.xxx", DISPATCH_QUEUE_SERIAL); |
执行函数与队列的关系
执行函数有同步(dispatch_sync
)和异步(dispatch_async
)之分,队列则有串行队列(DISPATCH_QUEUE_SERIAL
)和并发队列(DISPATCH_QUEUE_CONCURRENT
)之分。下面介绍不同的执行函数和队列组合时的任务执行情况。
同步函数和串行队列
- 任务在当前线程执行
- 任务按顺序执行
- 堵塞当前线程
同步函数和并发队列
- 任务在当前线程执行
- 任务按顺序执行
- 堵塞当前线程
异步函数和串行队列
- 创建一条新线程
- 任务按顺序执行
- 不会堵塞当前线程
异步函数和并发队列
- 创建新线程(至于能创建多少条新线程,由 CPU 和系统决定)
- 任务的执行顺序不定,由 CPU 的调度决定
- 不会堵塞当前线程