Search code examples
swiftobjective-cgrand-central-dispatch

Concurrent queue calls inside serial queue?


In Objective-C and Swift, is there any guarantee of order of execution for concurrent calls being made inside of a serial queue's async block?

Pseudo-code:

let serialQueue = SerialQueue()
let concurrentQueue = ConcurrentQueue()

serialQueue.async { // 1
    concurrentQueue.async { // 2
        run_task1() // task that takes 1 hour
    }
}

serialQueue.async { // 3
    concurrentQueue.async { // 4
        run_task2() // task that takes 1 minute
    }
}

In the above code, is task1 guaranteed to complete before task2 is called?

Or since they're called on a concurrent thread, the serial queue async only guarantees that run_task1 will be added to the concurrentQueue before run_task2, but not guarantee order of execution?


Solution

  • I've numbered the block in your question, so I can reference them here:

    Block 1 and 3 are both running on a serial queue, thus block 3 will only run once 1 is done.

    However, block 1 and 3 don't actually wait for task1/2, they just queue off work to happen asynchronously in blocks 2 and 4, which finishes near instantly.

    From then on, both task 1 and 2 will be running concurrently, and finish in an arbitrary order. The only guarantee is that task1 will start before task2.


    I always like to use the analogy of ordering a pizza vs making a pizza. Queuing async work is like ordering a pizza. It doesn't mean you have a pizza ready immediately, and you're not going to be blocked from doing other things while the pizzeria is baking your pizza.

    Your blocks 1 and 3 are strongly ordered, so 1 will finish and finish before 3 starts. However, all the block does is order a pizza, and that's fast. It does mean pizza 1 (task 1) is done before pizza 2 (task 2), it just means you got off the first phone call before making the second.