调用dispatch_sync()时死锁,即使它在另一个队列上

时间:2015-06-18 11:18:21

标签: objective-c cocoa concurrency grand-central-dispatch deadlock

我知道在当前队列中调用dispatch_async会导致死锁,但在完全不同的队列中遇到死锁:

-(void) deadlock{
    // we reach this point in the main queue
    dispatch_sync(dispatch_queue_create("lucas", 0), ^{
        NSLog(@"Doing something in the bakcgound...");
        // We reach this point in another queue, but it deadlocks!
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"Will I ever get here?????");
        });
    });
}

知道我做错了什么?

2 个答案:

答案 0 :(得分:2)

是的,这是一个僵局。就像你一直在创建一个

的例子一样
-(void) deadlock{

    // we reach this point in the main queue
    //and so main queue waits till this task will finish
    dispatch_sync(dispatch_queue_create("lucas", 0), ^{

        //doing something in background
        //while main queue still blocked by that dispatch_sync() call
        NSLog(@"Doing something in the bakcgound...");

        // We reach this point in another queue, but it deadlocks!
        //Of cause it does!!! Main queue is still waiting till task dispatched to "lucas" queue synchronously finishes. But it can't - waits for main queue to perform this later bock synchronously
        dispatch_sync(dispatch_get_main_queue(), ^{
             NSLog(@"Will I ever get here?????");
        });
    }); 
 }
 //we reach this point only after all code written above will performed. so, in our case, this point is unreachable either way 

因此,根据您的任务,您应该将此dispatch_sync()之一更改为dispatch_async()。

答案 1 :(得分:1)

Dispatch_sync在语义上等同于传统的互斥锁,而不是创建线程。尝试以下,将给你:“是主线程:1”。

dispatch_sync(dispatch_queue_create("lucas", 0), ^{

    NSLog(@"Doing something in the bakcgound...");
    NSLog(@"Is main thread: %d", [NSThread isMainThread]);

    // We reach this point in another queue, but it deadlocks!
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"Will I ever get here?????");
    });
});

你想要的我或多或少是following

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){

    NSLog(@"Doing something in the bakcgound...");

    dispatch_async(dispatch_get_main_queue(), ^(void){
         NSLog(@"Will I ever get here?????");
    });
});