Swift 调度队列异步执行顺序

Swift dispatch queues async order of execution

考虑这段微不足道的代码

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

print("1")

我们可以说输出如下:

1
2

在任何情况下执行顺序会有所不同(不考虑使用的队列类型)?有的话可以强制手动出现吗?

你说:

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

不,您充其量只能说输出将 often/frequently 按此顺序排列,但不能保证如此。

该代码片段正在将代码异步分派到一个全局并发队列,该队列将 运行 它放在一个单独的工作线程上,并且在没有任何同步的情况下,您在当前线程和那个工作线程。您无法保证这些 print 语句的顺序,但在实践中,您经常会在 2.

之前看到 1

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.

你的理解是正确的,这两个print语句的顺序是肯定不能保证的

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

几个想法:

  1. 例如,通过调整队列优先级,您可以更改 1 出现在 2 之前的可能性。但是,同样,不能保证。

  2. 有多种机制保证顺序。

    • 你可以使用串行队列...我知道你不想考虑使用 another/different 队列,但它通常是正确的解决方案,所以如果没有它,关于这个主题的任何讨论都是不完整的场景;
    • 可以使用dispatch group ...可以notify在当前队列满足group的情况下全局队列;
    • 您可以使用调度信号量...信号量是该问题的经典答案,但恕我直言,信号量应谨慎使用,因为它很容易出错...而且阻塞线程从来都不是一个好主意;
    • 为了完整起见,我们应该提到您确实可以使用任何 synchronization 机制,例如锁。

我也做了一个快速测试。通常我会在全局队列上的代码执行完成后进行 UI 更新,我通常会在代码块的末尾 step 2.

但是今天我突然发现即使我把那个主队列代码放在全局队列块的开头step 1,它仍然在所有全局队列代码执行完成后执行。

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")
    }
}

这是输出:

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