Grand Central Dispatch - 使用 GCD 同步 Swift 3 中的属性



我最近看了今年WWDC GCD的演讲,我认为有一个代码片段有问题。它是关于使用 DispatchQueues 使属性线程安全。

class MyObject {
    private var internalState: Int
    private let internalQueue: DispatchQueue // Serial or Concurrent?
    var state: Int {
        get {
            return internalQueue.sync { internalState }
        }
        set (newState) {
            internalQueue.sync { internalState = newState }
        }
    }
}

他们使用 DispatchQueue 来锁定属性。但我认为这个片段是无效的,因为内部队列可能是并发的。因此,如果我们从两个不同的 DispatchQueues/Threads 调用 setter,如果该内部队列不是串行的,它也可能导致线程问题,对吗?因为在我的理解中,同步只是保存调用线程并在任务完成时继续。您如何看待此片段?我错了吗?

我只想展示另一种方法,它使您能够并发阅读,但在使用调度屏障写入时阻止所有内容。

class MyObject {
private var internalState: Int
private let internalQueue = DispatchQueue(label: "reader-writer", attributes: .concurrent)
var state: Int {
    get {
        return internalQueue.sync { internalState }
    }
    set (newState) {
        internalQueue.async(flags: .barrier) { internalState = newState }
    }
  }
}

使用这种方法,读取可以在队列上并发发生,但由于存在障碍,写入是以独占方式执行的。

这只是 Matt Galloway 撰写的《Effective Objective C 2.0》一书中解释的方法的 Swift 3 转换。

但我认为这个代码段是无效的,因为内部队列可能是并发的

但它不是并发的。默认情况下,您创建的调度队列是串行的。这就是技术(和示例)的重点。

最新更新