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


当前回答

另一种方法是创建一个超类,然后继承它。这样你可以更直接地使用GCD

class Lockable {
    let lockableQ:dispatch_queue_t

    init() {
        lockableQ = dispatch_queue_create("com.blah.blah.\(self.dynamicType)", DISPATCH_QUEUE_SERIAL)
    }

    func lock(closure: () -> ()) {
        dispatch_sync(lockableQ, closure)
    }
}


class Foo: Lockable {

    func boo() {
        lock {
            ....... do something
        }
    }

其他回答

斯威夫特4

在Swift 4中,你可以使用gcd调度队列来锁定资源。

class MyObject {
    private var internalState: Int = 0
    private let internalQueue: DispatchQueue = DispatchQueue(label:"LockingQueue") // Serial by default

    var state: Int {
        get {
            return internalQueue.sync { internalState }
        }

        set (newState) {
            internalQueue.sync { internalState = newState }
        }
    }
} 

另一种方法是创建一个超类,然后继承它。这样你可以更直接地使用GCD

class Lockable {
    let lockableQ:dispatch_queue_t

    init() {
        lockableQ = dispatch_queue_create("com.blah.blah.\(self.dynamicType)", DISPATCH_QUEUE_SERIAL)
    }

    func lock(closure: () -> ()) {
        dispatch_sync(lockableQ, closure)
    }
}


class Foo: Lockable {

    func boo() {
        lock {
            ....... do something
        }
    }

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

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

    try block()
}

我自己也在寻找这个,并得出结论,在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!

为什么要让锁变得困难和麻烦呢? 使用分派障碍。

调度障碍在并发队列中创建同步点。 当它正在运行时,队列上的其他块都不允许运行,即使它是并发的并且其他内核可用。 如果这听起来像一个排他(写)锁,它是。 无障碍块可以被认为是共享(读)锁。 只要所有对资源的访问都是通过队列执行的,barrier就能提供非常廉价的同步。