lynk
lynk

Reputation: 153

If I have a dispatch_sync call followed by a second dispatch call within a dispatch_async block, does it matter if that second call is sync or async?

This code is for a pretty standard situation where I'm having my data model do some potentially slow data retrieval and I want to update my view with the data once the data retrieval finishes.

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_async(queue, ^{
    dispatch_sync(queue, ^{
        //get a bunch of data
    }
    dispatch_sync(dispatch_get_main_queue(), ^{
        [viewcontroller tellViewToReloadData];
    }
}

My question here is, does it make much of a difference if that second dispatch_sync was instead dispatch_async?

This is my understanding of what's happening with the code above (I'm also using this as an opportunity to gauge my understanding of this overall topic):

  1. The outer dispatch_async immediately returns, and the block with the two dispatch calls gets put into the concurrent queue.

  2. At some point the outer async block will execute on some random thread, at which point the first dispatch_sync gets called and its block gets put into the concurrent queue.

  3. At some point the inner first sync block will execute all of my data gathering operations on some random thread, and only when they are all finished will the first dispatch_sync return and the second dispatch_sync get called.

  4. The second dispatch_sync gets called, and the block with the code to update the view gets put into the main queue. At some point this block executes and the view gets updated, and the second dispatch_sync returns.

  5. The outer block is now finished executing so the concurrent queue is free to possibly push a task to the thread that was executing the outer block.

Now, my understanding is that if that second dispatch_sync was instead a dispatch_async call, the only change is that the thread executing the outer block is occupied for a slightly shorter amount of time because it doesn't have to wait for the block in the main queue to finish executing. Is this correct? By this reasoning it seems slightly better for the second dispatch_sync to be dispatch_async just because some thread will be occupied for a (probably trivially) shorter amount of time, but effectively it doesn't really matter.

Upvotes: 3

Views: 390

Answers (1)

user3125367
user3125367

Reputation: 3000

  1. First sync is pointless – you're already on queue.

    dispatch_async(queue, ^{
        //get a bunch of data
        dispatch_sync(dispatch_get_main_queue(), ^{
            [viewcontroller tellViewToReloadData];
        });
    });
    
  2. sync is just async with waiting primitive, as if it was:

    dispatch_semaphore_t s = dispatch_semaphore_create(0);
    
    dispatch_async(queue, ^{
        [viewcontroller tellViewToReloadData];
        dispatch_semaphore_signal(s);
    });
    
    dispatch_semaphore_wait(s, DISPATCH_TIME_FOREVER);
    

Now, my understanding is that if that second dispatch_sync was instead a dispatch_async call, the only change is that the thread executing the outer block is occupied for a slightly shorter amount of time because it doesn't have to wait for the block in the main queue to finish executing. Is this correct?

Yes.

By this reasoning it seems slightly better for the second dispatch_sync to be dispatch_async just because some thread will be occupied for a (probably trivially) shorter amount of time, but effectively it doesn't really matter.

It may matter in situations when many threads are stuck waiting for main thread to complete being under stress loads. Then system would need to spawn more pthreads to continue to perform other concurrent tasks effectively and close excessive threads afterwards. Can't tell if that applies, but obviously there is no need to wait if you don't need results.

Upvotes: 2

Related Questions