In Apple docs, it says:
Important: You should never call the dispatch_sync or dispatch_sync_f function from a task that is executing in the same queue that you are planning to pass to the function. This is particularly important for serial queues, which are guaranteed to deadlock, but should also be avoided for concurrent queues.
How do you write the code to do exactly this?
In short, a deadlock can occur when the system is waiting for a resource to free up while it's logically impossible for that resource to become available. You can think of this resource as almost anything.
The word Deadlock refers to a situation in which a set of different threads sharing the same resource are waiting for each other release the resource to finish its tasks. When working with the GCD, if we do not fully understand the GCD's concepts, we may create a deadlock in our code.
GCD is built on top of threads. Under the hood, it manages a shared thread pool. With GCD, you add blocks of code or work items to dispatch queues and GCD decides which thread to execute them on. As you structure your code, you'll find code blocks that can run simultaneously and some that should not.
Grand Central Dispatch is used in iOS to introduce concurrency and parallelism in the iOS applications, so that multiple heavy tasks are performed in the background, resulting in the smooth experience of the application usage, as the main thread is unaffected by the heavy background tasks.
An intentional deadlock on a certain queue:
dispatch_queue_t queue = dispatch_queue_create("my.label", DISPATCH_QUEUE_SERIAL); dispatch_async(queue, ^{ dispatch_sync(queue, ^{ // outer block is waiting for this inner block to complete, // inner block won't start before outer block finishes // => deadlock }); // this will never be reached });
It's clear here that the outer and inner blocks are operating on the same queue. Most cases where this will occur is in places where it's less obvious what queue the caller of the dispatch_sync
is operating on. This usually occurs in a (deeply) nested stack where you're executing code in some class that was originally launched on a certain queue, and by accident you call a dispatch_sync
to the same queue.
Simple code that creates deadlock:
dispatch_queue_t q = dispatch_queue_create("deadlock queue", DISPATCH_QUEUE_SERIAL); NSLog(@"1"); dispatch_async(q, ^{ NSLog(@"2"); dispatch_sync(q, ^{ NSLog(@"3"); }); NSLog(@"4"); }); NSLog(@"5");
Log output:
1 5 2
Here internal block is scheduled to be run on serial queue q
but it cannot run until current block is finished, while current block, in turn, waits internal to finish as we called it synchronously.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With