在主线程上安全使用NSLock吗?

时间:2019-10-04 00:01:50

标签: swift concurrency grand-central-dispatch nslock

我有一个全局变量,可以从多个线程(包括主线程)进行访问。我想使用NSLock because it’s faster than GCD

这就是我想要做的:

struct SynchronizedLock<Value> {
    private var _value: Value
    private var lock = NSLock()

    init(_ value: Value) {
        self._value = value
    }

    var value: Value {
        get { lock.synchronized { _value } }
        set { lock.synchronized { _value = newValue } }
    }

    mutating func synchronized<T>(block: (inout Value) throws -> T) rethrows -> T {
        return try lock.synchronized {
            try block(&_value)
        }
    }
}

extension NSLocking {
    func synchronized<T>(block: () throws -> T) rethrows -> T {
        lock()
        defer { unlock() }
        return try block()
    }
}

NSLock会阻塞主线程还是在主线程上使用安全? DispatchSemaphore的情况也是如此,应该诉诸队列吗?

1 个答案:

答案 0 :(得分:2)

是的,可以从任何线程(包括主线程)中使用NSLockNSLock的唯一限制是您必须从锁定它的同一线程中对其进行解锁。

  

NSLock会阻塞主线程还是在主线程上使用安全?

很明显,如果您在任何长时间内都阻塞了主线程,那将是有问题的。因此,请确保您总是非常快速地进出。始终避免长时间锁定(或阻塞)。

  

DispatchSemaphore的情况也是如此,应该诉诸队列吗?

任何同步机制都可以阻止正在使用它们的线程,因此无论采用哪种同步机制,这都存在很大的问题。 DispatchSemaphore或GCD串行队列都将具有与此锁定模式相同的问题。

您始终可以使用读取器-写入器模式,此模式会稍有缓解(该模式允许并发读取并且仅阻止写入)。

但是,作为一般规则,请限制您在同步机制中执行的操作。例如。如果您要进行昂贵的工作,请在本地线程中对特定线程尽力而为,并仅同步共享资源的最终更新。