部分相关概念
- 进程
一个正在执行的程序实例。作为线程的容器,是资源管理的单位。
每个进程都拥有独立且受保护的内存空间,用来存放程序正文和数据以及其打开的文件、子进程、即将发生的报警、信号处理程序、账号信息等。
iOS 中的后台只可以存在短暂的一段时间就会被挂起,在这种状态下进程将不会得到 CPU 时间片,当收到内存警告时,系统会将处于此状态的进程从内存中移除。
- 线程
执行进程中的所有任务。是 CPU 调度的基本单位。
线程只拥有程序计数器、寄存器、堆栈等少量资源,但与其他线程共享该进程的整个内存空间。
- 任务
表示的是一系列需要完成的工作。如 GCD 里的 Block 、performSelector 中的 selector。
- 队列
调度队列是一个对象。任务先进先出,不管是串行队列还是并发队列。
- 队列与线程
将任务加到队列中去执行,队列会根据同步或者异步添加,以及系统负载去控制线程并发数,然后调度线程去执行追加在队列上的任务。
- 并行
parallelism
在物理上真正的同时执行。
- 并发
concurrent
在逻辑上的同时执行,通过时间片轮转等调度算法实现的多任务同时执行。当在多核 CPU 实现并发时,多任务才是真正物理上的同时执行。
- 串行
按顺序执行任务,同一时间只执行一个任务。
- 串行与并行
有 a、b、c 三个任务,单个 CPU 处理分贝需要 1s、2s、3s。
同样用三个 CPU 进行处理a、b、c。
串行处理,需要6s。在各自的线程中完成,不会减少总的执行时间,反而会因为线程上下文的切换增加处理时间。
并行处理,只需要3s。
- 同步
发出一个调用后,得到结果才返回。
- 同步
发出一个调用后,不等得到结果就直接返回。
- 同步和异步
区别在于会不会阻塞当前线程,和任务的串行或并行没有关系。
有 a、b、c 三个任务,单个 CPU 处理分贝需要 3s、2s、1s。
同样用三个 CPU 进行处理a、b、c,若a是耗时计算相关的任务,b、c是 UI 相关的任务。
同步处理,需要3s去处理完a,然后再处理b、c的;
异步处理,处理a,调用后就马上接着处理b、c,不会等待a的处理完。
| 同步 | 异步 | |
|---|---|---|
| 主队列 | 在主线程中执行 | 在主线程中执行 |
| 串行队列 | 在当前线程中执行 | 新建线程执行 |
| 并发队列 | 在当前线程中执行 | 新建线程执行 |
GCD 死锁相关
dispatch_queue_t serialQueue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
- 主队列中同步添加任务 ❎
//->
//同步添加任务到主队列尾部 阻塞当前线程
//添加的任务要完成需要等待前面的任务完成
//前面的任务需要等待添加的任务完成后没有阻塞才能继续执行完成
//互相等待 死锁
dispatch_sync(mainQueue, ^{
NSLog(@"1"); // 任务1
});
- 串行队列中同步添加任务 ❎
//任务1
dispatch_sync(serialQueue, ^{
NSLog(@"1"); // 任务1
});
//任务1 ->
//同步添加任务a到串行队列(位置1的整个 block )
//执行任务1
//同步添加任务b到串行队列尾部(位置2的整个 block )
//a 的完成意味着 b 的完成
//b 在队列尾部,b 在 a 完成后才执行
//互相等待 死锁
dispatch_sync(serialQueue, ^{
//1
NSLog(@"1"); // 任务1
dispatch_sync(serialQueue, ^{
//2
NSLog(@"2"); // 任务2
});
});
dispatch_async(serialQueue, ^{
//1
NSLog(@"1"); // 任务1
dispatch_sync(serialQueue, ^{
//2
NSLog(@"2"); // 任务2
});
NSLog(@"3"); // 任务3
});
- 并发队列中同步添加任务 ✅
//任务1 -> 任务2 -> 任务3
dispatch_async(globalQueue, ^{
NSLog(@"1"); // 任务1
dispatch_sync(globalQueue, ^{
NSLog(@"2"); // 任务2
});
NSLog(@"3"); // 任务3
});
dispatch_apply串行队列 ❎
//1--0 ->
//dispatch_apply 会等待其所有的循环运行完成后再执行后面的任务
//同步添加任务a到串行队列(位置1的整个 block ),添加次数等同于 dispatch_apply 循环次数
//执行任务1
//同步添加任务b到串行队列尾部(位置2的整个 block )
//互相等待 死锁
dispatch_apply(2, serialQueue, ^(size_t i) {
//1
NSLog(@"1--%zu", i); // 任务1
dispatch_apply(2, serialQueue, ^(size_t i) {
//2
NSLog(@"2--%zu", i); // 任务2
});
});
NSLog(@"3"); // 任务3