1. 死锁场景1
/*在队列A 上面执行一个同步的Block 任务1*/
dispatch_sync(queueA, ^{
NSLog(@"队列A 上 block1 开始执行");
NSLog(@"block1 需要完成block任务2的执行才能够结束,此时进入阻塞状态,准备执行任务2");
NSLog(@"但是发现任务2同样是需要在队列A 上面执行一个同步的block,此刻队列A 已经进入阻塞状态,肯定是完不成任务2的执行的");
dispatch_sync(queueA, ^{
NSLog(@"A block 2");
/*在队列A 上面执行一个同步的Block 任务2*/
});
});
总结: 队列A 同步执行block1 ,进入阻塞,去执行子任务,但是因为已经阻塞,所以不能再执行其他同步阻塞任务,所以死锁了
可以通过dispatch_get_current_queue判断当前的执行队列去改进上述问题,不过该方法ios已经弃用了
API_DEPRECATED("unsupported interface", macos(10.6,10.9), ios(4.0,6.0))
该方法对于场景2的死锁是解决不了问题的,自行思考
改进后不会死锁:
dispatch_queue_t queueA = dispatch_queue_create("queueA", NULL);
dispatch_queue_t queueB = dispatch_queue_create("queueB", NULL);
dispatch_sync(queueA, ^{
NSLog(@"A block");
if (dispatch_get_current_queue() == queueA) {
NSLog(@"A block");
}else{
dispatch_sync(queueA, ^{
NSLog(@"A block");
});
}
});
2. 死锁场景2
注意和场景1的比较,这是升级版
dispatch_queue_t queueA = dispatch_queue_create("queueA", NULL);
dispatch_queue_t queueB = dispatch_queue_create("queueB", NULL);
dispatch_sync(queueA, ^{
NSLog(@"sync A a block")
dispatch_sync(queueB, ^{
NSLog(@"sync B a block")
dispatch_sync(queueA, ^{
NSInteger a = 12;
NSLog(@"%ld",a);
});
});
});
队列之间会形成一套层级体系,地位最高的那个队列总是"全局并发队列"(global concurrent queue),由于层级关系的存在,所以"检查当前队列是否为执行同步派发所用的队列"并不总是凑效。
派发队列层级体系
3.采用GCD 提供的 “队列特定数据” 来解决上述问题:待补充
总结
1.dispatch_get_current_queue 函数已经废弃,另外还有一些局限性,只做调试使用
2.由于队列层级的概念,所以无法用单个队列对象去描述或者代表"当前队列"这一个概念。
- 可以采用"队列特定数据"来解决同步队列的死锁问题