Swift: 使用 NSLock 或并发队列的安全线程

Swift: Safe Thread using NSLock or Concurrent Queue

最好的方法是什么Safe Thread

使用NSLock:

class Observable<T> {

    typealias Observer = (_ observable: Observable<T>, T) -> Void
    
    private var observers: [Observer]
    private let lock = NSLock()
    private var _value: T

    var value: T {
        get {
            lock.lock()
            let value = _value
            lock.unlock()
            return value
        }
        set {
            lock.lock()
            _value = newValue
            lock.unlock()
        }
    }

    
    init(_ value: T) {
        self._value = value
        observers = []
    }

    func observe(observer: @escaping Observer) {
        self.observers.append((observer))
    }

    private func notifyObservers(_ value: T) {
        DispatchQueue.main.async {
            self.observers.forEach { [unowned self](observer) in
                observer(self, value)
            }
        }
    }

}

使用Queue:

class SecondObservable<T> {

    typealias Observer = (_ observable: SecondObservable<T>, T) -> Void
    
    private var observers: [Observer]
    private let safeQueue = DispatchQueue(label: "com.observable.value", attributes: .concurrent)
    private var _value: T

    var value: T {
        get {
            var value: T!
            safeQueue.sync { value = _value }
            return value
        }
        set {
            safeQueue.async(flags: .barrier) { self._value = newValue }
        }
    }

    
    init(_ value: T) {
        self._value = value
        observers = []
    }

    func observe(observer: @escaping Observer) {
        self.observers.append((observer))
    }

    private func notifyObservers(_ value: T) {
        DispatchQueue.main.async {
            self.observers.forEach { [unowned self](observer) in
                observer(self, value)
            }
        }
    }

}

或连续Queue:

class ThirdObservable<T> {

    typealias Observer = (_ observable: ThirdObservable<T>, T) -> Void
    
    private var observers: [Observer]
    private let safeQueue = DispatchQueue(label: "com.observable.value")
    private var _value: T

    var value: T {
        get {
            var value: T!
            safeQueue.async { value = self._value }
            return value
        }
        set {
            safeQueue.async { self._value = newValue }
        }
    }

    
    init(_ value: T) {
        self._value = value
        observers = []
    }

    func observe(observer: @escaping Observer) {
        self.observers.append((observer))
    }

    private func notifyObservers(_ value: T) {
        DispatchQueue.main.async {
            self.observers.forEach { [unowned self](observer) in
                observer(self, value)
            }
        }
    }

}

NSLock 或具有 .concurrent 属性的 Queue 用于上述情况,为什么?

None 以上。非并发(串行)队列是最好的锁定形式。

在这种情况下,带有 barrier 标志的并发队列比使用 NSLock 更有效。

它们都阻止其他操作,而 setter 是 运行,但不同之处在于当您同时调用多个 getter 或并行时。

  • NSLock: 一次只允许 1 getter 运行
  • 具有 barrier 标志的并发队列:一次允许多个 getters 运行。