线程死锁产生的原因: 在一个串行队列的任务中, 再向这个队列添加同步任务.
典型例子:
image.png
我们分析一下:
image.png
主队列 main_queue 是一个串行队列, 串行队列的特点就是队列中所有任务必须顺序执行. 也就是说必须按照添加到队列中的先后顺序执行.
我们再看一张图:
image.png
我们在代码中使用 dispatch_sync() 函数给主队列添加了一个同步任务:
- - (void)viewDidLoad {
- [super viewDidLoad];
- dispatch_sync(dispatch_get_main_queue(), ^{
- NSLog(@"线程死锁");
- });
- }
也就是说后添加的同步任务 5 是在 viewDidLoad 任务 2 之后, 只有等待任务 2 执行完之后才能执行任务 5, 这就是串行队列的特点. 但是任务 5 是一个同步任务, 必须等任务 5 执行完才能执行其它任务, 因此造成互相等待的死锁.
再看一个例子
image.png
我们知道 GCD 分为同步任务和异步任务, 最开始的例子是主线程的主队列, 相当于是一个同步任务. 而这个例子证明了, 即便是在异步任务只要任务队列是串行队列, 在串行队列的任务中再向队列添加同步任务, 就会造成死锁, 关键点不是同步还是异步, 而是串行队列.
总结
dispatch_sync() 函数会阻塞线程. 当前队列是串行队列, 任务必须顺序执行. 在串行队列的任务 A 中给这个队列添加同步任务 B, 相当于说这个串行队列又多了一个任务 B, 任务 B 如果想要执行必须等待任务 A 执行完, 但是任务 B 是同步任务, 必须等任务 B 执行完才能执行其它任务, 所以任务 AB 互相等待, 造成死锁.
来源: http://www.jianshu.com/p/8bb77afd14e1