关于主线程执行同步任务造成死锁的思考
2020-07-03 本文已影响0人
本帅不良
经典问题重现
-(void)test2{
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"线程:%@",[NSThread currentThread]);
});
}
bug 粘贴 主线程+同步造成死锁
要想明白,为什么造成死锁,首先要搞懂主线程是干嘛的
主线程程序运行的主线,即:所有的代码都是在主线程中执行的。
明白这一点,我们就可以重现这个 bug 了
/*复现*/
-(void)test3{
NSLog(@"线程0:%@",[NSThread currentThread]);
//1
dispatch_queue_t queue = dispatch_queue_create("hello", DISPATCH_QUEUE_SERIAL);
//2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"线程1:%@",[NSThread currentThread]);
//3
dispatch_sync(queue, ^{
NSLog(@"线程1:%@",[NSThread currentThread]);
//4
dispatch_sync(queue, ^{
NSLog(@"2");
});
});
});
}
结果
复现
如下:
代码解读
1、创建一个名为“hello”的串行队列。
2、在全局队列(全局队列是一个并行队列)开启一个异步任务。目的是开启一个新的线程,在这个新的线程中模拟主线程遇到的死锁困境。
3、此时我们进入了一个新的线程,即我们模拟的主线程。在这个线程中,我们在一个串行队列中执行了一个同步操作。这个同步任务类似我们的 test3方法,这个名为 “hello” 的串行队列类似我们的主线程队列。
4、我们在这个 “hello”队列中又加入了一个新任务,新任务需要里面执行,但 3 中的任务还未结束,便形成了相互等待的状态,即为死锁。
我们可以看到两次的报错相同,证明我们的复现没有问题。
为进一步验证我们的结论我们做以下思考
同步+主线程会造成死锁,同步加串行确不会 同步+串行
我们再次复现,只需要稍微改下代码
复现
总结
主线程+同步造成死锁,是因为在串行队列中,某个任务还未结束,即开始新的任务,造成的。