你知道下面的输出顺序是什么吗?
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_queue_t worker_queue = dispatch_queue_create("worker", DISPATCH_QUEUE_SERIAL);
NSLog(@"0");
dispatch_async(worker_queue, ^{
NSLog(@"1");
});
dispatch_async(worker_queue, ^{
NSLog(@"2");
});
dispatch_sync(worker_queue, ^{
NSLog(@"3");
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"4");
});
});
NSLog(@"5");
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"6");
});
}
在查看答案之前可以先想一想你的答案,看看是否一样
点击查看答案
在回答这个问题之前,先说几个知识点
- 串行队列是先进先出的,先添加的任务一定是先执行的,主队列也是一个串行队列
- 当有一个同步任务要在串行队列中执行时,此时若队列中有其他任务未执行,则会先执行完其他任务之后,再执行这个同步任务
dispatch_sync造成死锁的条件是dispatch_sync所处的队列和dispatch_sync要执行任务的队列是同一个队列,并且该队列是串行队列,如下
dispatch_sync(worker_queue, ^{
/// 当前队列是worker_queue,并且要把打印任务也要在worker_queue同步中执行
dispatch_sync(worker_queue, ^{
NSLog(@"33");
});
NSLog(@"3");
});
接下来让我们分析一下代码
- 创建了一个串行队列worker_queue
- 打印0
- 添加一个异步任务(打印1)到worker_queue队列中
- 又添加一个异步任务(打印2)到worker_queue队列中
- 添加一个同步任务到worker_queue队列中
- 这里不会死锁,因为当前所处的队列是主队列,而任务执行的队列是worker_queue队列
- 由于是同步任务到串行队列,会按先进先出的顺序执行队列中的任务,依次打印1和2
- 然后执行同步任务打印3,并添加一个异步任务(打印4)到主队列中
- 打印5
- 添加一个异步任务(打印6)到主队列中
- 然后等主队列空闲之后,按照先进先出的顺序执行队列中的任务,依次打印4和6 所以答案是:0123546
如果你对上面的输出有疑问,强烈推荐你看看参考的这篇文章,对GCD源码的分析
如果本篇文章对你有帮助,能不能求个赞