iOS知识点总结-GCD同步死锁

下面这个程序会打印出什么结果:

1
2
3
4
5
6
7
-(void)syncDemo{
NSLog(@"打印1");
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"打印2");
});
NSLog(@"打印3");  
}

结果是:

1
2
2017-03-24 15:49:05.878072+0800 textDemo[726:286339] 打印1
(lldb)

并且有EXC_BAD_INSTRUCTION的报错信息

1
Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)

我们来一起分析一下这个过程。首先打印1,然后调用dispatch_sync(dispatch_get_main_queue()同步方法。GCD同步方法中需要执行打印2。于是就产生了死锁。我们一起来分析一下GCD的同步方法机制。同步方法:1,同于当前线程要做的事。做完主线程的一件事,才能再做下一件事。2,以block方法中的是事情做完为结束。

我们一起分析一下这个Demo的流程。首先打印1,然后调用sync方法。在主线程中,我需要执行sync方法。sync方法中有一个打印2的事情。也要在主线程去做。由于主线程同一时间只能做一件事。于是打印2需要等待sync方法完成再去执行。而sync同步方法的完成,需要等待block中的打印2完成。于是就形成了死锁。两个事件相互等待。

解决方案。将sync同步方法,替换成异步方法

1
2
3
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"打印2");
});

这样就可以看到正常打印了:

1
2
3
2017-03-24 16:34:20.208022+0800 textDemo[19419:343315] 打印1
2017-03-24 16:34:20.208206+0800 textDemo[19419:343315] 打印3
2017-03-24 16:34:20.211819+0800 textDemo[19419:343315] 打印2