GCD死锁概念:
使用GCD多线程编程时,如果同步函数dispatch_sync(),目标queue为当前queue,且queue为串行队列时,由于线程相互等待,会造成死锁,导致程序奔溃。
主线程运行如下代码:奔溃
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"queue");
});
或者:
// 串行队列
dispatch_queue_t queue = dispatch_queue_create("test.concurrent", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
dispatch_sync(queue, ^{
NSLog(@"bbb");
});
});
原因分析如下:
第一步:当代码执行到 dispatch_sync()时,会首先把dispatch_sync()函数放到当前线程的队列(就是主队列中),而且这个线程并不会立即返回,而是会等待block中的任务都完成时才会返回;
第二步:再把block中的任务依次放到主队列中等待执行;
由于是同步执行,而且block中的任务在主队列的线性表中的前面有个dispatch_sync()等待完成,而dispatch_sync()的完成又依赖于block的执行完成,就这样造成了死锁。
解决办法:
1.目标queue和函数所在queue不相同
NSLog(@"aaa");
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"bbb");
});
});
NSLog(@"ccc");
2.queue为并行队列
NSLog(@"aaa");
// 并行队列
dispatch_queue_t queue = dispatch_queue_create("test.concurrent", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue, ^{
dispatch_sync(queue, ^{
NSLog(@"bbb");
});
});
NSLog(@"ccc");