使用dispatch_sync进行死锁

tra*_*uan 5 iphone multithreading objective-c 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];
        });
    });
}
Run Code Online (Sandbox Code Playgroud)

我在这里遇到了僵局.根据Apple文档

"dispatch_sync":"将一个块提交给调度队列以进行同步执行.与dispatch_async不同,此函数在块完成之前不会返回.调用此函数并以当前队列为目标会导致死锁."

但是,我执行外部dispatch_sync操作myQueue,然后ditpatch_sync在不同的队列中执行内部操作,即`main_queue.

无法找出死锁的原因.任何评论/帮助在这里都很感激.

Mar*_*age 11

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

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

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

  • dispatch_async将在工作线程上执行块,但如果您碰巧直接或间接(通过目标队列)定位主队列,它也可能是主线程.这是一个实现细节,如果您不依赖它并且不考虑线程,而是考虑队列,以及代码的哪些部分需要异步或同步执行,那么这是最好的. (3认同)

Wai*_*ain 5

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

至少有一个呼叫需要dispatch_async.