在 Swift 中创建线程安全读取时,为什么在并发队列之外创建变量?

When creating thread safe reads in Swift, why is a variable create outside the concurrent queue?

public class Account {
    // MARK: Initializer
    // Custom initializer

    // MARK: Stored Properties
    let concurrentQueue: DispatchQueue = DispatchQueue(
        label: "concurrentQueue",
        qos: DispatchQoS.userInitiated,
        attributes: [DispatchQueue.Attributes.concurrent]
    ) 

    private var _name: String

    public name: String {
        get { 
            return self.concurrentQueue.sync { return self._name } 
        }

        set {
            self.concurrentQueue.async(flags: .barrier) {
                self._name = newValue
            }
        }
    }
}

假设您有一个像上面那样的 class 线程安全。

Accountclass中的getter和这样定义getter有什么区别?

get { 
    var result: String!
    self.concurrentQueue.sync { result = self._name } 
    return result
}    

我目前正在全神贯注于线程安全,我总是看到像后者那样创建读取。在我看来它们几乎是一样的...我错了吗?

来源:GCD Tutorial

没有区别。有两种DispatchQueue.sync方法:

public func sync(execute block: () -> Swift.Void)
public func sync<T>(execute work: () throws -> T) rethrows -> T

在你的第一个例子中使用了第二个:闭包可以 return 一个值,然后变成 return sync 调用的值。因此在

get { 
    return self.concurrentQueue.sync { return self._name } 
}

sync { ... } 的 return 值是 self._name 也就是 returned 来自 getter 方法。这相当于(但比)存储 临时变量中的值(这里是闭包 returns Void):

get { 
    var result: String!
    self.concurrentQueue.sync { result = self._name } 
    return result
}

当然这只适用于同步调度的闭包, 不是异步调用。这些存储起来供以后执行,必须 return Void:

public func async(..., execute work: @escaping @convention(block) () -> Swift.Void)