GCD自定义队列用于同步

时间:2015-05-23 01:23:05

标签: objective-c synchronization grand-central-dispatch

在Mike Ash的GCD article中,他提到:"自定义队列可以用作代替锁的同步机制。"

问题:

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

2)自定义队列是唯一的选择吗?我们不能将主队列用于同步目的吗?

1 个答案:

答案 0 :(得分:2)

首先,将任务提交到队列的调用是_sync还是_async,不会以任何方式影响任务是否与其他线程或任务同步。它只会影响调用者是否在任务完成执行之前被阻塞,或者是否可以继续执行。 _sync代表“同步”而_async代表“异步”,其声音类似但不同于“同步”和“未同步”。前者与线程安全无关,而后者则至关重要。

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

主队列是一个串行队列,因此它具有相同的属性。但是,任何提交到主队列的长时间运行任务都将阻止用户交互。如果任务不必与GUI交互或者具有在主线程上运行的类似要求,则最好使用自定义串行队列。

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

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

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