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


当前回答

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

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
  }
}

其他回答

总之,这里给出了更常见的方法,包括返回值或void和throw

import Foundation

extension NSObject {


    func synchronized<T>(lockObj: AnyObject!, closure: () throws -> T) rethrows ->  T
    {
        objc_sync_enter(lockObj)
        defer {
            objc_sync_exit(lockObj)
        }

        return try closure()
    }


}

你可以把语句夹在objc_sync_enter(obj: AnyObject?)和objc_sync_exit(obj: AnyObject?)之间。@synchronized关键字在幕后使用这些方法。即。

objc_sync_enter(self)
... synchronized code ...
objc_sync_exit(self)

我自己也在寻找这个,并得出结论,在swift中还没有对此的原生构造。

我确实根据我从Matt Bridges和其他人那里看到的一些代码编写了这个小的帮助函数。

func synced(_ lock: Any, closure: () -> ()) {
    objc_sync_enter(lock)
    closure()
    objc_sync_exit(lock)
}

用法非常简单

synced(self) {
    println("This is a synchronized closure")
}

我发现了一个问题。在这一点上,传入一个数组作为lock参数似乎会导致一个非常迟钝的编译器错误。除此之外,虽然它似乎工作如所愿。

Bitcast requires both operands to be pointer or neither
  %26 = bitcast i64 %25 to %objc_object*, !dbg !378
LLVM ERROR: Broken function found, compilation aborted!

在现代Swift 5中,具有返回功能:

/**
Makes sure no other thread reenters the closure before the one running has not returned
*/
@discardableResult
public func synchronized<T>(_ lock: AnyObject, closure:() -> T) -> T {
    objc_sync_enter(lock)
    defer { objc_sync_exit(lock) }

    return closure()
}

像这样使用它,以利用返回值功能:

let returnedValue = synchronized(self) { 
     // Your code here
     return yourCode()
}

或者像这样:

synchronized(self) { 
     // Your code here
    yourCode()
}

您可以创建propertyWrapper synchronized

这里是NSLock下罩的例子。你可以使用任何你想要的同步GCD, posix_locks等

@propertyWrapper public struct Synchronised<T> {
    private let lock = NSLock()

    private var _wrappedValue: T
    public var wrappedValue: T {
        get {
            lock.lock()
            defer {
                lock.unlock()
            }
            return _wrappedValue
        }
        set {
            lock.lock()
            defer {
                lock.unlock()
            }
            _wrappedValue = newValue
        }
    }

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

@Synchronised var example: String = "testing"

基于@drewster的答案