'OSSpinLock' устарел в iOS 10.0: вместо этого используйте os_unfair_lock() из <os/lock.h>

Я ответил на этот вопрос, но предоставленное решение не сработало. Может кто-нибудь объяснить любой альтернативный подход или правильную реализацию с использованием os_unfair_lock()?

когда я использую OS_UNFAIR_LOCK_INIT, он кажется недоступным.

Благодарность!

2 ответа

Решение

Ты можешь использовать os_unfair_lock как показано ниже,

var unfairLock = os_unfair_lock_s()

os_unfair_lock_lock(&unfairLock)
os_unfair_lock_unlock(&unfairLock)

В нас предупреждают, что мы не можем использовать напрямую в Swift, потому что «Swift предполагает, что все, что есть, может быть перемещено, а это не работает с мьютексом или блокировкой».

В этом видео спикер предлагает, чтобы, если вы должны использовать , вы поместили это в класс Objective-C (который не будет перемещать ). Или, если вы посмотрите на код stdlib , вы увидите, что вы можете оставаться в Swift, но использовать UnsafeMutablePointerвместо structнапрямую. (Спасибо bscothern за подтверждение этой закономерности .)

Так, например, вы можете написать UnfairLockкласс, который позволяет избежать этой проблемы:

      final class UnfairLock: NSLocking {
    private let unfairLock: UnsafeMutablePointer<os_unfair_lock> = {
        let pointer = UnsafeMutablePointer<os_unfair_lock>.allocate(capacity: 1)
        pointer.initialize(to: os_unfair_lock())
        return pointer
    }()

    deinit {
        unfairLock.deinitialize(count: 1)
        unfairLock.deallocate()
    }

    func lock() {
        os_unfair_lock_lock(unfairLock)
    }

    func tryLock() -> Bool {
        os_unfair_lock_trylock(unfairLock)
    }

    func unlock() {
        os_unfair_lock_unlock(unfairLock)
    }
}

Затем вы можете делать такие вещи, как:

      let lock = UnfairLock()

А затем используйте lockа также unlockкак вы бы с NSLock, но используя более эффективные за кулисами:

      lock.lock()
// critical section here
lock.unlock()

И поскольку это соответствует NSLocking, вы можете использовать расширения, предназначенные для этого. Например, вот общий метод, который мы используем, чтобы гарантировать, что наши блокировки и разблокировки сбалансированы:

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

А также

      lock.synchronized {
    // critical section here
}

Но суть в том, что не используйте os_unfair_lockот Swift без чего-то вроде вышеперечисленного или того, что рассматривается в этом Concurrent Programming With GCD in Swift 3видео , оба из которых предоставляют стабильный адрес памяти для блокировки.

Другие вопросы по тегам