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

Mic*_*sen 2 multithreading grand-central-dispatch ios swift

最好的办法是什么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)
            }
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

使用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)
            }
        }
    }

}

Run Code Online (Sandbox Code Playgroud)

或串行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)
            }
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

NSLock或上述情况的Queuewith.concurrent属性,为什么?

tru*_*duc 6

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

当 setter 运行时,它们都会阻止其他操作,但区别在于并发或并行调用多个 getter 时。

  • NSLock:一次只允许 1 个 getter运行
  • 带标志的并发队列barrier:允许同时运行多个 getter 。