What will happen if I have nested dispatch_async calls?

一笑奈何 提交于 2019-12-03 03:47:10

问题


It may be a dumb question but I need to ask and clear this up for myself.

To submit a block onto a queue for execution, use the functions dispatch_sync and dispatch_async. They both take a queue and a block as parameters. dispatch_async returns immediately, running the block asynchronously, while dispatch_sync blocks execution until the provided block returns. Here are some situations:

Situation 1

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul);    
dispatch_async(queue, ^{
    [self goDoSomethingLongAndInvolved];
    dispatch_async(queue, ^{
        NSLog(@"this is statement1");

    });
});

Situation 2

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul);    
dispatch_sync(queue, ^{
    [self goDoSomethingLongAndInvolved];
    dispatch_sync(queue, ^{
        NSLog(@"this is statement1");

    });
});

Situation 3

{
    [super viewDidLoad];
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul);    
    dispatch_async(queue, ^{
        [self goDoSomethingLongAndInvolved];
        dispatch_sync(queue, ^{
            NSLog(@"this is statement1");

        });
    });

Situation 4

{
    [super viewDidLoad];
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul);    
    dispatch_sync(queue, ^{
        [self goDoSomethingLongAndInvolved];
        dispatch_async(queue, ^{
            NSLog(@"this is statement1");

        });
    });

}

And goDoSomethingLongAndInvolved is

-(void)goDoSomethingLongAndInvolved {
    NSLog(@"goDoSomethingLongAndInvolved");
}

I tried to run them in Xcode but I cant see the difference at all.

So my questions are:

  1. What's the main difference between these situations?
  2. What if I replace queue with dispatch_get_main_queue()?

回答1:


The dispatch_sync statement waits until the block it covers is executed completely. dispatch_async returns immediately and proceeds to the next line of code, so everything inside is happening in parallel.

If queue was a serial queue created by yourself, then:

Situation 1 - The root block returns immediately. Inside it waits for [self go....], and then goes to dispatch_async, which returns immediately as well.

Situation 2 - If queue was a serial queue, then there would be a dead lock since it will wait for itself to finish executing. Since you are dealing with asynchronous one, that block will be executed in parallel. (Thanks, @Ken Thomases)

Situation 3 - No need in dispatch_sync here. It causes the deadlock.

Situation 4 - Waits for [self ...], then returns immediately.

If you replace the queue with main queue, then remember to not dispatch_sync on main queue, because it will cause a deadlock (it will not if dispatched not from main thread, thanks @Ken Thomases).

To understand it better, replace your function with:

-(void)goDoSomethingLongAndInvolved:(NSString *)message {
    for(int i = 0; i < 50; ++i) {
        NSLog(@"%@ -> %d", message, i); 
    }
}

You will clearly see what's going on every time, whether it waits or not. Good luck.



来源:https://stackoverflow.com/questions/18262066/what-will-happen-if-i-have-nested-dispatch-async-calls

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!