我已经搜索了Swift的书籍,但找不到@synchronized的Swift版本。我如何做互斥在Swift?


当前回答

使用Swift的属性包装器,这是我现在使用的:

@propertyWrapper public struct NCCSerialized<Wrapped> {
    private let queue = DispatchQueue(label: "com.nuclearcyborg.NCCSerialized_\(UUID().uuidString)")

    private var _wrappedValue: Wrapped
    public var wrappedValue: Wrapped {
        get { queue.sync { _wrappedValue } }
        set { queue.sync { _wrappedValue = newValue } }
    }

    public init(wrappedValue: Wrapped) {
        self._wrappedValue = wrappedValue
    }
}

然后你可以这样做:

@NCCSerialized var foo: Int = 10

or

@NCCSerialized var myData: [SomeStruct] = []

然后像往常一样访问变量。

其他回答

要添加返回函数,你可以这样做:

func synchronize<T>(lockObj: AnyObject!, closure: ()->T) -> T
{
  objc_sync_enter(lockObj)
  var retVal: T = closure()
  objc_sync_exit(lockObj)
  return retVal
}

随后,你可以调用它使用:

func importantMethod(...) -> Bool {
  return synchronize(self) {
    if(feelLikeReturningTrue) { return true }
    // do other things
    if(feelLikeReturningTrueNow) { return true }
    // more things
    return whatIFeelLike ? true : false
  }
}

你可以使用GCD。它比@synchronized更详细一点,但可以作为替代品:

let serialQueue = DispatchQueue(label: "com.test.mySerialQueue")
serialQueue.sync {
    // code
}

在Swift4中使用NSLock:

let lock = NSLock()
lock.lock()
if isRunning == true {
        print("Service IS running ==> please wait")
        return
} else {
    print("Service not running")
}
isRunning = true
lock.unlock()

警告 NSLock类使用POSIX线程来实现它的锁定行为。当向NSLock对象发送解锁消息时,必须确保该消息是从发送初始锁定消息的同一个线程发送的。从不同的线程解锁锁可能会导致未定义的行为。

使用Bryan McLemore的答案,我扩展了它,以支持使用Swift 2.0延迟能力扔进安全庄园的对象。

func synchronized( lock:AnyObject, block:() throws -> Void ) rethrows
{
    objc_sync_enter(lock)
    defer {
        objc_sync_exit(lock)
    }

    try block()
}

斯威夫特3

此代码具有重入能力,可以与异步函数调用一起工作。在这段代码中,someAsyncFunc()被调用之后,串行队列上的另一个函数闭包将被处理,但会被semapore .wait()阻塞,直到signal()被调用。internalQueue。不应该使用sync,因为如果我没有弄错的话,它会阻塞主线程。

let internalQueue = DispatchQueue(label: "serialQueue")
let semaphore = DispatchSemaphore(value: 1)

internalQueue.async {

    self.semaphore.wait()

    // Critical section

    someAsyncFunc() {

        // Do some work here

        self.semaphore.signal()
    }
}

如果没有错误处理,Objc_sync_enter /objc_sync_exit不是一个好主意。