GCD中的Dispatch_barrier_async和串行队列,它们之间有什么区别?

时间:2016-10-01 04:19:47

标签: ios grand-central-dispatch

我发现 dispatch_barrier_async 的工作机制是,只有在先前添加到队列中的所有块都已完成后才会执行。它的工作原理类似于串行队列。

因此,我不区分GCD中这两种运行模式之间的差异。

enter image description here

3 个答案:

答案 0 :(得分:20)

dispatch_barrier_[a]sync旨在与并发队列一起使用。它们也可以与dispatch_[a]sync的调用一起使用。

常见的用法是"多读者,一个作家"图案。您设置并发队列。对于"读者"阻止,你使用dispatch_[a]sync。对于"作家"阻止,您使用dispatch_barrier_[a]sync

此设置允许并发读取,但一次只允许一个编写者,而在写入时不会读取。

将此与串行队列进行比较,其中一次只能发生一个块。

答案 1 :(得分:9)

您的图表完美地说明了障碍如何运作。七个块已被分派到一个并发队列,四个没有屏障(图中的块0到3),一个带有屏障(褐色的“屏障块”在图中编号为4),然后是另外两个没有屏障的块屏障(图中的方框5和6)。

正如你所看到的,前四个同时运行,但是阻挡块在前四个完成之前不会运行。最后两个在“障碍块”结束之前不会开始。

将其与串行队列进行比较,其中没有任何任务可以同时运行:

comparison

如果调度到并发队列的每个块都使用屏障调度,那么你是对的,它等同于使用串行队列。但是,只有在并发队列中将屏障调度块与非屏障调度块组合在一起时,障碍的威力才会发挥作用。因此,当您想要享受并发行为时,请不要使用障碍。但是,如果单个块在并发队列上需要类似串行的行为,请使用屏障。

一个例子是你可能会派出10个没有障碍的街区,但是然后添加一个带障碍的第11个街区。因此前10个可以相互同时运行,但是第11个只会在前10个结束时开始(实现“完成处理程序”行为)。

或者正如rmaddy所说(+ 1),障碍的另一个常见用途是您访问某些共享资源,您将允许并发读取(没有障碍),但必须强制执行同步写入(使用屏障)。在这种情况下,您经常使用dispatch_sync进行读取,使用dispatch_barrier_async进行写入。

答案 2 :(得分:1)

#swift5

两者都用于同步, 所以串行队列确保你所有的工作都在一个堆栈中完成 例如,如果您有 A、B、C、D 任务,如果它们是同步或异步的,它们将按相同的顺序执行 同步阻止其他操作的执行,直到同步块完成。

Barrier:允许您在堆栈中进行同步操作,但它允许您进行异步操作以读取这些值,因此 在数据结构实现方面更强大 你只有一个作者有多个读者。

func asyncReading() {
    DispatchQueue.global(qos: .background)
        .async(group: .init(), qos: .background, flags: .barrier) {
            /// Read code.
        }
}

func syncWriting() {
    DispatchQueue.global(qos: .background)
        .sync(group: .init(), qos: .background, flags: .barrier) {
            /// Write code.
        }
}