理解顺序
1、主线程有且只要一个队列,即主队列,用于UI刷新。通过这个dispatch_get_main_queue()
可以获取主队列。
2、dispatch_sync
因为是同步操作,需要等待block执行完成,才返回。
3、如果当前线程为主线程,传入队列为主队列,那么调用dispatch_sync
即阻塞主队列,而block
中又等待主队列的完成,主队列不完成,dispatch_sync
也不返回,造成循环的等待,也就是死锁。
官方文档:
dispatch_sync(dispatch_queue_t queue, DISPATCH_NOESCAPE dispatch_block_t block);
将block中的内容提交给指定的队列,并同步执行:
Submits a block object for execution on a dispatch queue and waits until that block completes.
值得注意的:
将块提交给分派队列以进行同步执行。与dispatch_async不同,这个函数直到块完成才返回。调用此函数并针对当前队列会导致死锁。
Submits a block to a dispatch queue for synchronous execution. Unlike dispatch_async, this function does not return until the block has finished. Calling this function and targeting the current queue results in deadlock.
重要的事情:
current queue
current queue
current queue
这里着重理解“当前队列”,一般我们当前队列就是主线程的队列,也就是主队列:dispatch_get_main_queue(),也就是说,如果dispatch_sync传入的队列,不是当前队列,则不会出现死锁。
当前队列为主队列,直接这样写,会造成死锁:
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"执行");
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"死锁,不执行");
});
NSLog(@"不执行");
}
执行结果:
2018-12-03 15:31:11.849985+0800 testtest[2581:512553] 执行,当前队列:<NSThread: 0x60000006d700>{number = 1, name = main}
如果dispatch_sync(dispatch_get_main_queue(), ^{});
这种写法,放在的队列不是当前队列:
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"1,当前队列:%@",[NSThread currentThread]);
dispatch_queue_t queue = dispatch_queue_create("123", NULL);
//切换当前队列为自定义的队列
dispatch_async(queue, ^{
NSLog(@"2,当前队列:%@",[NSThread currentThread]);
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"3,当前队列:%@",[NSThread currentThread]);
});
});
NSLog(@"4");
}
执行结果:
2018-12-03 15:46:18.361870+0800 testtest[2731:536556] 1,当前队列:<NSThread: 0x6040000640c0>{number = 1, name = main}
2018-12-03 15:46:18.362098+0800 testtest[2731:536556] 4
2018-12-03 15:46:18.362177+0800 testtest[2731:536668] 2,当前队列:<NSThread: 0x60400047c9c0>{number = 4, name = (null)}
2018-12-03 15:46:18.404327+0800 testtest[2731:536556] 3,当前队列:<NSThread: 0x6040000640c0>{number = 1, name = main}
相同队列的操作:
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"1,当前队列:%@",[NSThread currentThread]);
dispatch_queue_t queue = dispatch_queue_create("123", NULL);
dispatch_async(queue, ^{
NSLog(@"2,当前队列:%@",[NSThread currentThread]);
dispatch_sync(queue, ^{
NSLog(@"3,当前队列:%@",[NSThread currentThread]);
});
});
NSLog(@"4");
}
执行结果:
2018-12-03 16:12:15.326599+0800 testtest[2956:573733] 1,当前队列:<NSThread: 0x604000075180>{number = 1, name = main}
2018-12-03 16:12:15.326838+0800 testtest[2956:573733] 4
2018-12-03 16:12:15.326908+0800 testtest[2956:573835] 2,当前队列:<NSThread: 0x600000479380>{number = 4, name = (null)}
总结
因此,要知道dispatch_sync是否会死锁,需要知道当前队列和传入的队列是否是同一个。如果是同一个,才会造成死锁。而不是说,这样写:dispatch_sync(dispatch_get_main_queue(), ^{});
就一定会死锁。
网友评论