Безопасно ли использовать NSLock в основном потоке? - PullRequest
1 голос
/ 04 октября 2019

У меня есть глобальная переменная, доступ к которой осуществляется из нескольких потоков, в том числе из основного потока. Я хотел бы использовать NSLock , потому что он быстрее, чем 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 Ответ

2 голосов
/ 04 октября 2019

Да, безопасно использовать NSLock из любого потока, включая основной поток. Единственное ограничение с NSLock состоит в том, что вы должны разблокировать его из того же потока, который вы заблокировали, что вы делаете здесь.

NSLock заблокирует основной поток или это безопасноиспользовать в главном потоке?

Очевидно, что если вы заблокируете основной поток на длительный период времени, это будет проблематично. Поэтому убедитесь, что вы всегда входите и выходите очень быстро. Всегда избегайте блокировок (или блокировок) на любой длительный период времени.

Также это та же самая ситуация с DispatchSemaphore и следует прибегать к очередям?

Любая синхронизацияМеханизм может блокировать поток, из которого они используются, поэтому он в значительной степени проблематичен независимо от механизма синхронизации. DispatchSemaphore или в последовательных очередях GCD обе будут иметь ту же проблему, что и этот шаблон блокировки.

Вы всегда можете использовать шаблон чтения-записи, который немного смягчает это (когда он допускает одновременное чтение и только блокирует запись).

Но, как правило, ограничивайте объем работы механизма синхронизации. Например, если вы делаете что-то дорогое, делайте как можно больше в локальных сетях с конкретным потоком и синхронизируйте только окончательное обновление общего ресурса.

...