iOS 底层 day19 多线程基本概念 GCD线程死锁总结
2020-09-14 本文已影响0人
望穿秋水小作坊
一. 关于多线程中的一些基本概念
1. iOS 中有几种多线程方案有哪几种?分别简述一下。
主要记住 GCD 和 NSOperation 部分二. GCD 中的一些基本概念 和 线程死锁总结
1. GCD 中有 2 个用来执行任务的函数
- 用
同步
的方式来执行任务:
dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
- 用
异步
的方式来执行任务:
dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
2. 比较容易混淆的术语
同步
和异步
主要影响:能不能开启新的线程-
同步
:在当前
线程执行任务,不具备
开启新线程的能力 -
异步
:在新的
线程执行任务,具备
开启新线程的能力 并发
和串行
主要影响:任务的执行方式-
并行
:多个
任务并发(同时)执行 -
串行
:一个
执行完毕后,再执行下一个任务
三. GCD 中一些串行、并行、同步、异步的问题
1. 下面代码会造成死锁吗?
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"任务1");
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"任务2");
});
NSLog(@"任务3");
}
- 会死锁
- 仅打印
任务1
- 可以将
viewDidLoad
看成一个大任务
,大任务已经在主队列(串行队列)
的头部执行了,串行队列的特点是先进先出
。 - 这时候,我们又往
主队列(串行队列)
里面塞了个任务2的block
,在主队列(串行队列)
中任务二
必须等大任务
执行完毕。 - 但是
大任务
执行到dispatch_sync
,又要求必须先执行任务2的block
,这样就引发矛盾了,就形成了死锁。
2. 下面代码会造成死锁吗?
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"任务一");
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"任务二");
});
NSLog(@"任务三");
}
- 不会
- 日志
任务一
任务三
任务二
3. 下面代码会造成死锁吗?
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"任务一");
dispatch_queue_t queue = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"任务二");
dispatch_sync(queue, ^{
NSLog(@"任务三");
});
NSLog(@"任务四");
});
NSLog(@"任务五");
}
- 会死锁
- 日志:
任务一 任务五 任务二
4. 下面代码会造成死锁吗?
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"任务一");
dispatch_queue_t queue = dispatch_queue_create("queue1", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"任务二");
dispatch_sync(queue, ^{
NSLog(@"任务三");
});
NSLog(@"任务四");
});
NSLog(@"任务五");
}
- 不会死锁
- 日志:
任务一 任务五 任务二 任务三 任务四
5. 下面代码会造成死锁吗?
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"任务一");
dispatch_queue_t queue = dispatch_queue_create("queue1", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue, ^{
NSLog(@"任务二");
dispatch_sync(queue, ^{
NSLog(@"任务三");
});
NSLog(@"任务四");
});
NSLog(@"任务五");
}
- 不会死锁
- 日志:
任务一 任务二 任务三 任务四 任务五