简体   繁体   中英

Swift dispatch queues async order of execution

Considering this trivial piece of code

DispatchQueue.global().async {
    print("2")
}

print("1")

we can say that output will be as following:

1
2

Are there any circumstances under which order of execution will be different (disregarding kind of used queue)? May they be forced to appear manually if any?

You said:

we can say that output will be as following ...

No, at best you can only say that the output will often/frequently be in that order, but is not guaranteed to be so.

The code snippet is dispatching code asynchronously to a global, concurrent queue, which will run it on a separate worker thread, and, in the absence of any synchronization, you have a classic race condition between the current thread and that worker thread. You have no guarantee of the sequence of these print statements, though, in practice, you will frequently see 1 before 2 .

this is one of the common questions at tech interview; and for some reason interviewers expect conclusion that order of execution is constant here. So (as it was not aligned with my understanding) I decided to clarify.

Your understanding is correct, that the sequence of these two print statements is definitely not guaranteed.

Are there any circumstances under which order of execution will be different

A couple of thoughts:

  1. By adjusting queue priorities, for example, you can change the likelihood that 1 will appear before 2 . But, again, not guaranteed.

  2. There are a variety of mechanisms to guarantee the order.

    • You can use a serial queue ... I gather you didn't want to consider using another/different queue, but it is generally the right solution, so any discussion on this topic would be incomplete without that scenario;
    • You can use dispatch group ... you can notify on the global queue when the current queue satisfies the group;
    • You can use dispatch semaphores ... semaphores are a classic answer to the question, but IMHO semaphores should used sparingly as it's so easy to make mistakes ... plus blocking threads is never a good idea;
    • For the sake of completeness, we should mention that you really can use any synchronization mechanism, such as locks.

I do a quick test too. Normally I will do a UI update after code execution on global queue is complete, and I would usually put in the end of code block step 2 .

But today I suddenly found even I put that main queue code in the beginning of global queue block step 1 , it still is executed after all global queue code execution is completed.

DispatchQueue.global().async {
    // step 1
    DispatchQueue.main.async {
        print("1. on the main thread")
    }
    
    // code global queue
    print("1. off the main thread")
    print("2. off the main thread")
    
    // step 2
    DispatchQueue.main.async {
        print("2. on the main thread")
    }
}

Here is the output:

1. off the main thread
2. off the main thread
1. on the main thread
2. on the main thread

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM