2
votes

So I'm putting 10 tasks on a concurrent queue using dispatch_async. They do not block the next task, and gets processed in order. My UI is responsive.

for (int i = 0; i < 10; i++) {

    dispatch_async(concurrencyQueue, ^() {

        NSLog(@"..calling insertion method to insert record %d", i);

           dispatch_sync(serialQueue, ^() {

            //this is to simulate writing to database
            NSLog(@"----------START %d---------", i);
            [NSThread sleepForTimeInterval:1.0f];
            NSLog(@"--------FINISHED %d--------", i);

        });

    });
}

Within each task, we simulate a write to database with a "1 sec sleep" on a serial Queue via dispatch_sync.

I always thought dispatch_sync blocks everyone, and syncs its tasks because that's how it behaves when I use it individually. However, in this situation, it does not block the main thread. Instead, it runs beautifully in the background like I want it.

Is it because whatever thread is associated with the queue is being affected?

For example, the main thread is executing the concurrent queue via dispatch_async and that's why it is not blocked.

The dispatch_sync only syncs and blocks against the background thread that's working on the concurrent queue. Hence, the dispatch_sync is associated with the background thread, thus never affecting my UI main thread.

Is my thinking correct?

thank you!

2

2 Answers

3
votes

You never block the main thread because your code is running on either the threads of the concurrencyQueue or the thread of the serialQueue. None of those are the main thread.

All of the calls to sleep happen one by one on the thread of the serialQueue. So it is the thread of the serialQueue that is blocked.

However, since you dispatch to the serialQueue using dispatch_sync, you are also blocking each thread of the concurrent queue. This would be better pictured if you add another NSLog after the call to dispatch_sync.

for (int i = 0; i < 10; i++) {
    dispatch_async(concurrencyQueue, ^() {
        NSLog(@"..calling insertion method to insert record %d", i);

        dispatch_sync(serialQueue, ^() {
            //this is to simulate writing to database
            NSLog(@"----------START %d---------", i);
            [NSThread sleepForTimeInterval:1.0f];
            NSLog(@"--------FINISHED %d--------", i);
        });

        NSLog(@"..called insertion method to insert record %d", i);
    });
}

That 2nd NSLog after the dispatch_sync will show you better how the dispatch_sync is affecting the calls to dispatch_async.

2
votes

Yes, you are right. dispatch_sync() blocks only the thread the queue is running on.