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.
}
}
我发现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.
}
}