【发布时间】:2017-02-09 17:00:36
【问题描述】:
【问题讨论】:
标签: ios multithreading grand-central-dispatch barrier
【问题讨论】:
标签: ios multithreading grand-central-dispatch barrier
dispatch_barrier_[a]sync 用于并发队列。它们还应与对dispatch_[a]sync 的调用一起使用。
常见的用法是“多位读者,一位作者”模式。您设置了一个并发队列。对于“阅读器”块,您使用dispatch_[a]sync。对于“作家”块,您使用dispatch_barrier_[a]sync。
此设置允许并发读取,但一次只允许一个写入器,并且在写入发生时不允许读取。
将此与一次只能发生一个块的串行队列进行比较。
【讨论】:
您的图表完美地说明了障碍的工作原理。七个块已被分派到并发队列,四个没有障碍(图中的块 0 到 3),一个有障碍(图中的栗色“障碍块”编号为 4),然后还有两个没有障碍的块障碍(图中的块 5 和 6)。
如您所见,前四个同时运行,但障碍块在前四个完成之前不会运行。而后两个要等到“屏障”完成后才会开始。
将其与串行队列进行比较,其中没有任何任务可以同时运行:
如果分派到并发队列的每个块都使用屏障分派,那么您是对的,这相当于使用串行队列。但是,只有当您将屏障调度的块与并发队列上的非屏障调度的块结合起来时,屏障的力量才会发挥作用。所以,当你想享受并发行为时,不要使用障碍。但是,如果单个块需要在并发队列上进行类似串行的行为,请使用屏障。
一个例子是,您可以分派 10 个没有障碍的块,然后添加第 11 个带障碍的块。因此,前 10 个可能彼此同时运行,但第 11 个只会在前 10 个完成时开始(实现“完成处理程序”行为)。
或者正如 rmaddy 所说 (+1),屏障的另一个常见用途是访问一些共享资源,您将允许并发读取(无屏障),但必须强制执行同步写入(使用屏障)。在这种情况下,您通常使用dispatch_sync 进行读取,使用dispatch_barrier_async 进行写入。
【讨论】:
#swift5
它们都用于同步, 所以串行队列确保你所有的工作都在一个堆栈中完成 例如,如果您有 A、B、C、D 任务,如果它们是同步或异步的,它们将按相同的顺序执行 在同步块完成之前,同步会阻止其他操作执行。
障碍:允许您在堆栈中执行同步操作,但它允许您执行异步操作以读取这些值,因此 在数据结构实现方面它更强大 你只有一个作家和多个读者。
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.
}
}
【讨论】:
.sync(group: .init() 是什么,没有其他答案。