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类来避免这个问题:
2条答案
按热度按时间yi0zb3m41#
在iOS 16(和macOS 13)及更高版本中,您应该使用
OSAllocatedUnfairLock
。正如documentation所说:在Swift中使用
os_unfair_lock
是不安全的,因为它是一种值类型,因此没有稳定的内存地址。这意味着当你调用os_unfair_lock_lock
或os_unfair_lock_unlock
并使用&
操作符传递一个锁对象时,系统可能会锁定或解锁错误的对象。相反,使用
OSAllocatedUnfairLock
,它避免了这个缺陷,因为它不作为值类型,尽管是一个结构。OSAllocatedUnfairLock
的所有复制示例控制相同的底层锁分配。因此,如果您希望以线程安全的方式与计数器交互:
对于早期操作系统版本的支持,请参阅下面我的原始答案。
在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
类来避免这个问题:然后,您可以执行以下操作:
然后像使用
NSLock
一样使用lock
和unlock
,但在幕后使用更高效的os_unfair_lock
:因为这符合
NSLocking
,所以你可以使用为此设计的扩展。例如,这里是一个常见的方法,我们用来保证我们的锁和解锁是平衡的:然后呢
但是,底线是,不要使用来自Swift的
os_unfair_lock
,如果没有上面的东西或video中的预期,这两者都为锁提供了稳定的内存地址。dojqjjoe2#
你可以像下面这样使用
os_unfair_lock
,