Dispatch_queue_t is a sequential queue, why does it even exist in a multi-task concept?

I am new to iPhone development and am looking at the concept of GCD for multithreading.

'dispatch_queue_t' creates a sequential queue and I read that a sequential queue will only do one job at a time. GCD is designed to run multiple tasks at the same time, why is there another queue?

For example, I want to complete 2 tasks. Task A and Task B. I create one sequential queue to do both of these tasks. I do this in the main queue. Here is the code I am doing:

dispatch_queue_t my_serial_queue = dispatch_queue_create("queue_identifier", 0);

    dispatch_sync(my_serial_queue, ^{
        NSLog(@"Task 1");
    });

    dispatch_sync(my_serial_queue, ^{
        NSLog(@"Task 2");
    });

      

Now, according to the rule, both tasks will be executed sequentially, since it is a sequential queue, that is, task A is executed first, and then after task A completes, task B is executed and it also gives me the same result in the log.

So my question is, what if I want to do both tasks at the same time? If the answer to this question is to create another queue for task B, then the code should be structured like this:

dispatch_queue_t my_serial_queue_1 = dispatch_queue_create("queue_identifier_1", 0);
dispatch_queue_t my_serial_queue_2 = dispatch_queue_create("queue_identifier_2", 0);


    dispatch_sync(my_serial_queue_1, ^{
        NSLog(@"Task 1");
    });

    dispatch_sync(my_serial_queue_2, ^{
        NSLog(@"Task 2");
    });

      

I am getting the same result. The reason is that I am using the dispatch_sync call instead of the dispatch_async call. But since I am running both tasks on different queues, they shouldn't be running at the same time? If not, why should we create another queue? I could use the same queue when calling 'dispatch_async' to execute both tasks at the same time.

I really need an answer to this question, because before I design my multitasking application framework in the future, it helps me better.

Appreciate your advice. Thanks in advance.

+3


source to share


2 answers


Your confusion is entirely due to the fact that you are using dispatch_sync. dispatch_sync is not a concurrency tool, it is a tool to temporarily limit its security.

Once you use dispatch_async you can get concurrency with either multiple queues or parallel queues. The purpose of using sequential queues in this context is to control what work is done at the same time.

Consider the following very silly example:

__block void *shared = NULL;
for (;;) {
    dispatch_async(aConcurrentDispatchQueue, ^{
        shared = malloc(128);
        free(shared);
    }
}

      



this will work because, in the end, two of the concurrently executing blocks will free the 'shared' on the line. Obviously this is a contrived example, but in practice, almost all shared state variables shouldn't change at the same time. Serial queues are your tool to ensure that you do this.

To summarize:

  • When the work in your blocks is truly independent and thread safe and purely computational, keep using dispatch_async on a parallel queue
  • When you have logically independent tasks, each of which consists of several related blocks, use a sequential queue for each task.
  • When you have work that accesses shared mutable state, do those calls in dispatch_sync () ed blocks on the sequential queue, and the rest of the work on the parallel queue
  • When you need to do UI related work, dispatch_async or dispatch_sync on the main queue, depending on whether you want to wait for completion or not.
+4


source


'dispatch_queue_t' does not create anything. dispatch_queue_t - dispatch queue, serial or parallel.

dispatch_queue_create has two parameters. The second parameter determines whether the generated queue will be a serial or parallel queue. But usually you don't create parallel queues yourself, but use one of the three existing parallel queues.

dispatch_sync dispatches a block to the queue and waits until the block is complete. Obviously this is very restrictive on concurrency. You should almost always use dispatch_async.



Consecutive queues can only execute one block at a time. Obviously this is very restrictive on concurrency. Sequential queues are still useful when you need to execute different blocks one after the other, and they can run concurrently with blocks in other queues.

So for maximum CPU utilization use dispatch_async on a parallel queue. And there is no need to create multiple parallel queues. It is at the same time. It can run any number of blocks at the same time.

+1


source







All Articles