OK, I love Grand Central Dispatch and after using it with relative success but this is something I don't fully understand.
Suppose I have created my own serial queue using
dispatch_queue_t myQueue;
myQueue = dispatch_queue_create("myQueue", NULL);
After that I do this:
dispatch_async(myQueue, ^{
[self doStuff1];
});
// and a few lines later...
dispatch_sync(myQueue, ^{
[self doStuff2];
});
The first dispatch is async. So, it will be done concurrently, right? How can that be if myQueue is serial? How can a serial queue do things in parallel or, if you will, out of order?
thanks
Understanding Queues As mentioned before, GCD operates on dispatch queues through a class aptly named DispatchQueue . You submit units of work to this queue, and GCD executes them in a FIFO order (first in, first out), guaranteeing that the first task submitted is the first one started.
Since its concurrent queue, tasks may not finish in the order they are added to queue. But with synchronous operation it does although they may be processed by different threads. So, it behaves as this is the serial queue. Remember using GCD you are only adding task to the Queue and performing task from that queue.
Concurrent queues (also known as a type of global dispatch queue) execute one or more tasks concurrently, but tasks are still started in the order in which they were added to the queue. The currently executing tasks run on distinct threads that are managed by the dispatch queue.
Yes, the dispatch queue objects, themselves, are thread-safe (i.e. you can safely dispatch to a queue from whatever thread you want), but that doesn't mean that your own code is necessarily thread-safe.
dispatch_async()
means that the block is enqueued and dispatch_async()
returns to enqueueing another task/block (possibly) prior to the block being executed.
With dispatch_sync()
, the block is enqueued and the function will not continue enqueueing another task/block until the block is executed.
The blocks are still executed serially. You could execute 100 dispatch_async()
calls, each with a block that sleeps for 100 seconds, and it'd be really fast. Follow that with a call to dispatch_sync()
on the same serial queue and dispatch_sync()
will return ~10,000 seconds later.
To put it more simply:
dispatch_async(serialQ, block1);
dispatch_async(serialQ, block2);
dispatch_sync(serialQ, block3);
block1
will be executed before block2
which will be executed before block3
. That is the order guaranteed by the serial queue.
However, the calls to dispatch_async()
may return before any of the blocks start executing. The dispatch_sync()
will not return before all three blocks are executed!
Neither dispatch_async
or dispatch_sync
change the way the block gets queued. If the queue is serial, the blocks will execute in a serial manner, if the queue is concurrent, in a concurrent manner.
The important difference between the two is that dispatch_sync
queues the block and waits on the current execution thread until that block is executed and dispatch_async
just queues the block and continues the execution of the subsequent instructions.
Serial Queue can only run a single task at a time,irrespective of sync or async. Serial queues are allocated only one thread. This will be easier to understand using the below example -
Suppose there are 2 Queues A and B running tasks T1 and T2 respectively and T1 is being executed asynchronously. If control passes from A to B and B runs T2 synchronously then till the time the T2(block of code in the dispatch_sync block) completes execution T1 will be blocked. When T2 completes then T1 will resume it's execution.
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