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

Tru*_*an1 3 concurrency grand-central-dispatch nslock swift

我有一个从多个线程(包括主线程)访问的全局变量。我\xe2\x80\x99d 喜欢使用 NSLock因为它\xe2\x80\x99s 比 GCD 快

\n\n

Here\xe2\x80\x99s 我\xe2\x80\x99m 试图做的事情:

\n\n
struct SynchronizedLock<Value> {\n    private var _value: Value\n    private var lock = NSLock()\n\n    init(_ value: Value) {\n        self._value = value\n    }\n\n    var value: Value {\n        get { lock.synchronized { _value } }\n        set { lock.synchronized { _value = newValue } }\n    }\n\n    mutating func synchronized<T>(block: (inout Value) throws -> T) rethrows -> T {\n        return try lock.synchronized {\n            try block(&_value)\n        }\n    }\n}\n\nextension NSLocking {\n    func synchronized<T>(block: () throws -> T) rethrows -> T {\n        lock()\n        defer { unlock() }\n        return try block()\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

NSLock阻塞主线程还是在主线程上使用安全?这是否也是同样的情况并且DispatchSemaphore应该诉诸队列?

\n

Rob*_*Rob 5

NSLock是的,它可以从任何线程(包括主线程)安全地使用。唯一的限制NSLock是您必须从锁定它的同一个线程解锁它,正如您在这里所做的那样。

\n\n
\n

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

\n
\n\n

显然,如果您长时间阻塞主线程,就会出现问题。因此,请确保您始终快速进出。始终避免长时间锁定(或阻塞)。

\n\n
\n

这是否也是同样的情况并且DispatchSemaphore应该诉诸队列?

\n
\n\n

任何同步机制都可以阻止使用它们的线程,因此无论同步机制如何,它都会产生很大的问题。DispatchSemaphore或 GCD 串行队列都会遇到与此锁定模式相同的问题。

\n\n

您始终可以使用读写器模式,这会稍微缓解这种情况(它允许并发读取并且仅阻止写入)。

\n\n

但作为一般规则,请限制您在同步机制中执行的操作。例如,如果您\xe2\x80\x99正在做一些昂贵的事情,请在特定线程的局部变量中尽可能多地执行操作,并且仅同步共享资源的最终更新。

\n