我制作了一个自定义属性包装器,它提供了一种使用互斥上下文访问数据的方法os_unfair_lock
。在启用 TSAN 的情况下测试我的包装器后,在使用以下命令获取锁时报告了访问争用错误os_unfair_lock_lock
(如下图所示)
不知何故,TSAN 报告认为线程安全的锁定结构并非如此。这里发生了什么?
一种替代(可能更直接)的方法来解决您的问题自我回答 https://stackoverflow.com/a/68614553/169394是直接在 Swift 中堆分配锁,而不是桥接到 Objective-C 来执行此操作。 Objective-C 方法通过从不同的语言调用具有不同语义的锁定函数来避免这个问题——C 和 Objective-C 不会move或通过 inout 引用传递给函数的墓碑值类型;但你也可以通过完全不使用 inout 引用来避免纯 Swift 中的问题:
let lock = UnsafeMutablePointer<os_unfair_lock>.allocate(capacity: 1)
lock.initialize(to: .init())
// later:
os_unfair_lock_lock(lock)
defer { os_unfair_lock_unlock(lock) }
堆分配允许您将指针直接传递到函数中,并且指针是参考Swift 中的类型——虽然 Swift 可以移动指针值本身,但它引用的内存将保持不变(并且有效)。
如果您走这条路,当您想要拆除锁时,请不要忘记取消初始化并释放内存:
lock.deinitialize(count: 1)
lock.deallocate()
如果您愿意,您可以创建一个类似的UnfairLock
Swift 中的接口,包括像您自己的功能mutexExecute
:
typealias UnfairLock = UnsafeMutablePointer<os_unfair_lock>
extension UnfairLock {
static func createLock() -> UnfairLock {
let l = UnfairLock.allocate(capacity: 1)
l.initialize(to: .init())
return l
}
static func destructLock(_ lock: UnfairLock) {
lock.deinitialize(count: 1)
lock.deallocate()
}
func whileLocked<T>(_ action: () throws -> T) rethrows -> T {
os_unfair_lock_lock(self)
defer { os_unfair_lock_unlock(self) }
return try action()
}
}
Usage:
init() {
lock = UnfairLock.createLock()
}
deinit {
UnfairLock.destructLock(lock)
}
func performThing() -> Foo {
return lock.whileLocked {
// some operation that returns a Foo
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)