iOS-多线程

关于主线程执行同步任务造成死锁的思考

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 中的任务还未结束,便形成了相互等待的状态,即为死锁。

我们可以看到两次的报错相同,证明我们的复现没有问题。

为进一步验证我们的结论我们做以下思考

同步+主线程会造成死锁,同步加串行确不会 同步+串行

我们再次复现,只需要稍微改下代码


复现
总结

主线程+同步造成死锁,是因为在串行队列中,某个任务还未结束,即开始新的任务,造成的。

上一篇 下一篇

猜你喜欢

热点阅读