我刚在objc.io全异步上读到这个,但是找不到很好的解释
dispatch_queue_t queueA; // assume we have this
dispatch_sync(queueA, ^(){ // (a)
dispatch_sync(queueA, ^(){ // (b)
foo();
});
});一旦我们进入第二个dispatch_sync,我们就会陷入死锁:我们不能将消息分派到queueA上,因为某个人(当前的线程)已经在这个队列上了,并且永远不会离开它。
只要我能理解
我已经阅读了许多与此相关的线程,如同步、同步当前队列?、同步()调用冻结?、.但找不到好的解释。有人说dispatch_sync阻塞队列,有人说它阻塞当前线程. :(
那么,它为什么会导致僵局呢?
发布于 2014-05-29 18:02:12
dispatch_sync阻塞当前线程,直到分派的代码完成为止,如果您从串行队列同步发送,那么您也有效地阻塞了队列。因此,如果同步地从串行队列发送到自身,则会导致死锁。
但是要明确的是,dispatch_sync阻塞当前线程,而不是当前队列。在处理并发队列时,将对随后分派的块使用不同的工作线程,而不会导致死锁。
您似乎是在响应“并发编程指南”调度队列一章末尾的讨论,该章节指出:
不要从在传递给函数调用的相同队列上执行的任务调用
dispatch_sync函数。这样做会使队列死锁。如果需要向当前队列分派,请使用dispatch_async函数异步执行。
这不是完全正确的。如果(a)使用并发队列执行此操作;(b)存在可用的工作线程,则不会导致死锁。但这是一种糟糕的做法,尽管如此,还是应该避免的。
发布于 2015-09-06 12:34:01
使用此代码可以从任何线程调用主线程,而不会发生死锁。请记住,如果队列的层次结构很深,您仍然会陷入僵局。
static inline void dispatch_synchronized (dispatch_queue_t queue,
dispatch_block_t block)
{
dispatch_queue_set_specific (queue, (__bridge const void *)(queue), (void *)1, NULL);
if (dispatch_get_specific ((__bridge const void *)(queue)))
block ();
else
dispatch_sync (queue, block);
}https://stackoverflow.com/questions/23939730
复制相似问题