死锁是怎样炼成的

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        dispatch_sync(dispatch_get_main_queue(), ^(void){
            NSLog(@"zhixing");
        });
    }
    return 0;
}

执行这个dispatch_get_main_queue队列的是主线程。执行了dispatch_sync函数时,将block添加到了main_queue中,同时调用dispatch_syn这个函数的线程,也是主线程,主线程既要调用dispatch_syn又要执行block,所以主线程被阻塞,主线程想要等待block执行完成,而block的执行希望主线程来调用它。所以主线程处于阻塞状态,block永远不会被执行。

综上,主线程执行dispatch_sync容易发生死锁。

把上面的例子改一下:

dispatch_queue_t queue = dispatch_queue_create("SimaSDK", nil);
dispatch_sync(queue, ^(void){
NSLog(@"这个也不会死锁");
});

因为这时主线程虽然在block返回前会被阻塞,但当GCD分配的线程执行完block后,函数就会返回,主线程不会继续被阻塞。所以不会死锁。

综上,如果同步的向另外一个串行队列添加方法,并不一定导致死锁。而异步执行一定不会导致死锁。

事实上,导致死锁的原因一定是:
另外,因为队列是可以嵌套的,比如在A队列(串行)添加一个任务a,在a这个任务中向B队列(串行)添加任务b,在b这个任务中又向A队列添加任务,这就间接满足了“在某一个串行队列中,同步的向这个队列添加block”。但是我们好像每一次都没有直接向相同的队列中添加block。
A<---a
B<---b,然后a等待b先执行完,
然后b又等待A队列里的a任务执行完之后再往A队列里面加入新任务。

所以:判断是否发生死锁的最好方法就是看有没有在串行队列(当然也包括主队列)中向这个队列添加任务。

你可能感兴趣的:(死锁是怎样炼成的)