首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >dispatch_sync在dispatch_sync中会导致死锁

dispatch_sync在dispatch_sync中会导致死锁
EN

Stack Overflow用户
提问于 2014-05-29 17:52:01
回答 2查看 2.8K关注 0票数 4

我刚在objc.io全异步上读到这个,但是找不到很好的解释

代码语言:javascript
运行
复制
dispatch_queue_t queueA; // assume we have this
dispatch_sync(queueA, ^(){  // (a)
    dispatch_sync(queueA, ^(){ // (b)
        foo();
    });
});

一旦我们进入第二个dispatch_sync,我们就会陷入死锁:我们不能将消息分派到queueA上,因为某个人(当前的线程)已经在这个队列上了,并且永远不会离开它。

只要我能理解

  1. threadWorkItem只需将工作项添加到queueA中(我避免使用“块”这个词,因为它可能会混淆),那么这个工作项将被发送到queueA的目标队列中,然后GCD将为该工作项保留一个线程queueA。
  2. 当我到达(b)时,我在线程threadWorkItem中(假设threadWorkItem是这个线程的名称),所以我认为将另一个工作项排队到queueA没有问题。但是有人说,此时,queueA被保存,queueA被阻塞,->导致死锁,这使我感到困惑。

我已经阅读了许多与此相关的线程,如同步同步当前队列?同步()调用冻结?、.但找不到好的解释。有人说dispatch_sync阻塞队列,有人说它阻塞当前线程. :(

那么,它为什么会导致僵局呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-05-29 18:02:12

dispatch_sync阻塞当前线程,直到分派的代码完成为止,如果您从串行队列同步发送,那么您也有效地阻塞了队列。因此,如果同步地从串行队列发送到自身,则会导致死锁。

但是要明确的是,dispatch_sync阻塞当前线程,而不是当前队列。在处理并发队列时,将对随后分派的块使用不同的工作线程,而不会导致死锁。

您似乎是在响应“并发编程指南”调度队列一章末尾的讨论,该章节指出:

不要从在传递给函数调用的相同队列上执行的任务调用dispatch_sync函数。这样做会使队列死锁。如果需要向当前队列分派,请使用dispatch_async函数异步执行。

这不是完全正确的。如果(a)使用并发队列执行此操作;(b)存在可用的工作线程,则不会导致死锁。但这是一种糟糕的做法,尽管如此,还是应该避免的。

票数 13
EN

Stack Overflow用户

发布于 2015-09-06 12:34:01

使用此代码可以从任何线程调用主线程,而不会发生死锁。请记住,如果队列的层次结构很深,您仍然会陷入僵局。

代码语言:javascript
运行
复制
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);
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23939730

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档