用于同步的 GCD 自定义队列

GCD custom queue for synchronization

在 Mike Ash 的 GCD article 中,他提到:"Custom queues can be used as a synchronization mechanism in place of locks."

问题:

1) dispatch_barrier_async 与 dispatch_async 有何不同? dispatch_async 是否实现了与 dispatch_barrier_async 同步相同的功能?

2) 自定义队列是唯一的选择吗?我们不能使用主队列进行同步吗?

首先,提交任务到队列的调用是_sync还是_async丝毫不影响该任务是否与其他线程或任务同步。它只影响调用者是否被阻塞直到任务完成执行或者它是否可以继续。 _sync代表"synchronous",_async代表"asynchronous",与"synchronized"、"unsynchronized"读音相似但又不同。前者与线程安全无关,后者至关重要

您可以使用串行队列来同步对共享数据结构的访问。串行队列一次只执行一个任务。因此,如果所有涉及给定数据结构的任务都提交到同一个串行队列,那么它们将永远不会同时执行,并且它们对数据结构的访问将是安全的。

主队列是一个串行队列,所以它有相同的属性。但是,任何提交到主队列的long-运行ning任务都会阻塞用户交互。如果任务不必与 GUI 交互或有与它们在主线程上 运行 类似的要求,最好使用自定义串行队列。

如果您使用屏障例程,也可以使用自定义并发队列实现同步。 dispatch_barrier_async()dispatch_async()不同的是队列暂时变成了串行队列,或多或少。当屏障任务到达队列的头部时,它不会启动,直到该队列中的所有先前任务都完成。一旦他们这样做了,屏障任务就会被执行。在屏障任务完成之前,队列不会启动它持有的任何后续任务。

提交到并发队列的非障碍任务可能 运行 彼此同时进行,这意味着它们不同步,如果它们访问共享数据结构,它们可能会破坏该数据结构或得到不正确的结果等

屏障例程对于读写同步很有用。只要没有线程试图同时修改(写入)数据结构,多个线程同时从数据结构读取通常是安全的。修改或写入数据结构的任务不得 运行 同时与读者或其他作者同时进行。这可以通过将读取任务作为非障碍任务提交到给定队列并将写入任务作为障碍任务提交到同一队列来实现。