“OSSpinLock”在iOS 10.0中已弃用:请改用〈os/lock. h>中的os_fairly_lock()函数

twh00eeo  于 2023-03-31  发布在  iOS
关注(0)|答案(2)|浏览(180)

我经历了这个Question,但提供的解决方案不起作用。有人能解释任何替代方法或正确的实现使用os_unfair_lock()吗?
当我使用“OS_UNFAIR_LOCK_INIT”时,它似乎不可用。

谢谢!

yi0zb3m4

yi0zb3m41#

在iOS 16(和macOS 13)及更高版本中,您应该使用OSAllocatedUnfairLock。正如documentation所说:
在Swift中使用os_unfair_lock是不安全的,因为它是一种值类型,因此没有稳定的内存地址。这意味着当你调用os_unfair_lock_lockos_unfair_lock_unlock并使用&操作符传递一个锁对象时,系统可能会锁定或解锁错误的对象。
相反,使用OSAllocatedUnfairLock,它避免了这个缺陷,因为它不作为值类型,尽管是一个结构。OSAllocatedUnfairLock的所有复制示例控制相同的底层锁分配。
因此,如果您希望以线程安全的方式与计数器交互:

import os.lock

let counter = OSAllocatedUnfairLock(initialState: 0)

...

counter.withLock { value in
    value += 1
}

...

counter.withLock { value in
    print(value)
}

对于早期操作系统版本的支持,请参阅下面我的原始答案。
Concurrent Programming With GCD in Swift 3中,他们警告我们不能在Swift中直接使用os_unfair_lock,因为“Swift假设任何struct都可以移动,而这不适用于互斥锁或锁。
在那个视频中,演讲者建议如果你必须使用os_unfair_lock,你可以把它放在Objective-C类中(这不会移动struct)。或者如果你看一些stdlib代码,他们显示你可以留在Swift中,但直接使用UnsafeMutablePointer而不是struct。(感谢bscothern的confirming this pattern。)
例如,你可以写一个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()

然后像使用NSLock一样使用lockunlock,但在幕后使用更高效的os_unfair_lock

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

因为这符合NSLocking,所以你可以使用为此设计的扩展。例如,这里是一个常见的方法,我们用来保证我们的锁和解锁是平衡的:

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

然后呢

lock.withLock {
    // critical section here
}

但是,底线是,不要使用来自Swift的os_unfair_lock,如果没有上面的东西或video中的预期,这两者都为锁提供了稳定的内存地址。

dojqjjoe

dojqjjoe2#

你可以像下面这样使用os_unfair_lock

var unfairLock = os_unfair_lock_s()

os_unfair_lock_lock(&unfairLock)
os_unfair_lock_unlock(&unfairLock)

相关问题