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

Dispatch_barrier_async and serial queue in GCD, what're differences between them?

我发现dispatch_barrier_async的工作机制是,只有之前加入队列的block都完成了才会执行。它的工作方式类似于串行队列。

所以我不去区分这两种运行模式在GCD中有什么区别

dispatch_barrier_[a]sync 用于并发队列。它们还应与对 dispatch_[a]sync.

的调用一起使用

常见的用法是 "multi-readers, one writer" 模式。您设置了一个并发队列。对于 "reader" 个块,您使用 dispatch_[a]sync。对于 "writer" 个块,您使用 dispatch_barrier_[a]sync.

此设置允许并发读取,但一次只允许一位写入者,并且在写入时不允许读取。

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

您的图表完美地说明了屏障的工作原理。七个块已被分派到并发队列,四个没有屏障(图中的块 0 到块 3),一个有屏障(栗色的“屏障块”在你的图中编号为 4),然后还有两个没有屏障的块障碍(图表中的块 5 和 6)。

如您所见,前四个 运行 并发,但障碍块不会 运行 直到前四个完成。最后两个要到 "barrier block" 结束后才会开始。

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

如果分派到并发队列的每个块都使用屏障分派,那么你是对的,这相当于使用串行队列。但是,只有在并发队列中将屏障分派块与非屏障分派块结合使用时,屏障的威力才会发挥作用。所以,当你想享受并发行为时,不要使用障碍。但是,如果单个块需要在并发队列上进行类似串行的行为,请使用屏障。

一个例子是,您可以分派 10 个没有障碍的区块,然后添加第 11 个有障碍的区块。因此,前 10 个可能 运行 彼此并发,但第 11 个只会在前 10 个完成时开始(实现 "completion handler" 行为)。

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

#swift5

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

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

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.
        }
}