答案 0 :(得分:20)
dispatch_barrier_[a]sync
旨在与并发队列一起使用。它们也可以与dispatch_[a]sync
的调用一起使用。
常见的用法是"多读者,一个作家"图案。您设置并发队列。对于"读者"阻止,你使用dispatch_[a]sync
。对于"作家"阻止,您使用dispatch_barrier_[a]sync
。
此设置允许并发读取,但一次只允许一个编写者,而在写入时不会读取。
将此与串行队列进行比较,其中一次只能发生一个块。
答案 1 :(得分:9)
您的图表完美地说明了障碍如何运作。七个块已被分派到一个并发队列,四个没有屏障(图中的块0到3),一个带有屏障(褐色的“屏障块”在图中编号为4),然后是另外两个没有屏障的块屏障(图中的方框5和6)。
正如你所看到的,前四个同时运行,但是阻挡块在前四个完成之前不会运行。最后两个在“障碍块”结束之前不会开始。
将其与串行队列进行比较,其中没有任何任务可以同时运行:
如果调度到并发队列的每个块都使用屏障调度,那么你是对的,它等同于使用串行队列。但是,只有在并发队列中将屏障调度块与非屏障调度块组合在一起时,障碍的威力才会发挥作用。因此,当您想要享受并发行为时,请不要使用障碍。但是,如果单个块在并发队列上需要类似串行的行为,请使用屏障。
一个例子是你可能会派出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.
}
}