如何同步对具有didSet的属性的访问?

时间:2017-05-17 05:05:26

标签: swift grand-central-dispatch synchronized

如何同步使用didSet的属性的访问权限(使用GCD或objc_sync_enter)?

我有一个属性有一个属性观察者。如何使用私有队列来同步属性的get / set

var state: State = .disconnected {
  // Q: How to sync get/set access here?
  didSet {
    // do something
  }
}

2 个答案:

答案 0 :(得分:2)

最简单的方法是使用串行队列

import Dispatch

struct S {
    private var i: Int = 0 {
        didSet {
            print("someone did set new value:", i)
        }
    }
    private let queue = DispatchQueue(label: "private", qos: .userInteractive) // high priority
    var value: Int {
        get {
            return queue.sync {
                return i
            }
        }
        set {
            if newValue == value {
                return
            }
            queue.sync {
                i = newValue
            }
        }
    }
}

更高级的示例使用并发读取和同步屏障进行写入

import Dispatch

struct S {
    private var i: Int = 0 {
        didSet {
            print("someone did set new value:", i)
        }
    }
    private let queue = DispatchQueue(label: "private", qos: .userInteractive, attributes: .concurrent) // high priority
    var value: Int {
        get {
            return queue.sync {
                return i
            }
        }
        set {
            if newValue == value {
                return
            }
            queue.sync(flags: .barrier) {
                i = newValue
            }
        }
    }
}

在类属性的情况下,您可以使用并发专用队列并同时从不同的线程读取并使用屏障异步调度写入

import Dispatch

class S {
    private var i: Int = 0 {
        didSet {
            print("someone did set new value:", i)
        }
    }
    private let queue = DispatchQueue(label: "private", qos: .userInteractive, attributes: .concurrent) // high priority
    var value: Int {
        get {
            return queue.sync {
                return i
            }
        }
        set {
            if newValue == value {
                return
            }
            queue.async(flags: .barrier) { [unowned self] in
                self.i = newValue
            }
        }
    }
}

答案 1 :(得分:0)

替代(使用objc_sync_enter):

class MyUtil {

  class func synchronize(_ blockObj: AnyObject!, closure: () -> Void) {
    objc_sync_enter(blockObj)
    closure()
    objc_sync_exit(blockObj)
  }
  class func synchronize<T>(_ blockObj: AnyObject!, closure: () -> T) -> T {
    objc_sync_enter(blockObj)
    let retVal:T = closure()
    objc_sync_exit(blockObj)
    return retVal
  }
}

struct S {
  private var i: Int = 0 {
    didSet {
        print("someone did set new value:", i)
    }
  }
  var value: Int {
    get {
        return MyUtil.synchronize(i as AnyObject) {
            return i
        }
    }
    set {
        MyUtil.synchronize(i as AnyObject) {
          if newValue == value {
              return
          }
          i = newValue
        }
    }
}