使用dispatch_sync进行死锁

时间:2013-08-18 08:20:06

标签: iphone objective-c multithreading grand-central-dispatch

{
    dispatch_queue_t myQueue = dispatch_queue_create("com.mycompany.myqueue", 0);

    dispatch_sync(myQueue, ^{

        //Do EXTREME PROCESSING!!!
        for (int i = 0; i< 100; i++) {
            [NSThread sleepForTimeInterval:.05];
            NSLog(@"%i", i);
        }

        dispatch_sync(dispatch_get_main_queue(), ^{
            [self updateLabelWhenBackgroundDone];
        });
    });
}

我在这里陷入僵局。根据Apple文档

  

“dispatch_sync”:“将块提交到调度队列以进行同步   执行。与dispatch_async不同,此函数直到返回为止   块已经完成。调用此功能并定位   当前队列导致死锁。“。

但是,我在dispatch_sync上执行外部myQueue,然后在另一个名为“main_queue”的队列中执行内部ditpatch_sync

无法找出死锁的原因。任何评论/帮助都在这里赞赏。

3 个答案:

答案 0 :(得分:10)

如果像这样调度_sync到myQueue并且调用发生在主线程上,那么dispatch_sync将尽可能在那里执行块,而不是像dispatch_async那样在新的工作线程上执行。您无法保证为您的队列获得单独的工作线程。

然后该块在主线程上运行,直到它遇到第二个dispatch_sync调用,该调用恰好以主队列为目标。该队列无法提供服务,因为已经有一个块在运行,这就是你最终陷入僵局的地方。

如果这是您的问题,即第一个dispatch_sync确实来自主线程,那么您应该切换到dispatch_async。您不希望使用长时间运行的“EXTREME PROCESSING”操作来阻止主线程。

答案 1 :(得分:5)

您正在拨打dispatch_sync两次。第一次挂起主线程等待您的块完成。然后该块使用第二个调用挂起后台线程,该第二个调用尝试回送到主线程(由于它被挂起,它将永远不会从其队列中处理该块)。两个线程现在都在互相等待。

至少有一个电话需要dispatch_async

答案 2 :(得分:2)

我有类似的问题,这些解决方案都没有奏效。我问过比我聪明的人。

我的问题是我正在派遣一个异步工作块,然后显示一个进度窗口。通过

回调主线程
  

dispatch_sync(dispatch_get_main_queue(),^ {})

失败,异步调用失败。

解释是主线程不再处于公共模式&#39;因为模态窗口。我用这个替换了我对主线程的调用....

CFRunLoopPerformBlock(([[NSRunLoop mainRunLoop] getCFRunLoop]), (__bridge CFStringRef)NSModalPanelRunLoopMode, ^{
        //Update UI thread.

    });