我的应用程序使用一个类A
及其子类SubA_x
。
A
有一个静态属性,该属性仅在初始化子类时serialNumber
由类修改。它设置一个属性,以便每个子类都有一个唯一的名称。以下是代码:A
let name
class A {
static var serialNumber = 0
let name: String
init( /* some parameters */ ) {
A.serialNumber += 1
self.name = "\(A.serialNumber)"
}
}
final class SubA_1: A {
init( /* some parameters */ ) {
super.init( /* some parameters */ )
}
}
使用 Swift 6 严格并发检查时,初始化的行serialNumber
会出现错误
静态属性“serialNumber”不是并发安全的,因为它是非独立的全局共享可变状态
我知道每个子类都A
可以var serialNumber
从任何线程进行修改,因此数据竞争是可能的。
但是我如何以并发安全的方式实现此功能?
serialNumber
我尝试通过演员提供:
actor SerialNumberManager {
private var serialNumber = 0
func getNextSerialNumber() -> Int {
serialNumber += 1
return serialNumber
}
}
但我无法getNextSerialNumber()
在 中调用init
,除非init
是异步的。但我只能在异步上下文中初始化子类,等等。
我可能可以根据 GCD 提供自己的同步,但应该有一种方法可以在 Swift 并发中做到这一点。
如果您想要一个线程安全的共享状态,那么这
actor
是一种合乎逻辑的方法。但是,如果您想要一个可以从同步上下文中调用的管理器,那么您可以编写自己的管理器,实现自己的手动同步(使用 GCD 串行队列或如下所示使用锁):@unchecked Sendable
请注意,我们仅会在实现手动同步时才会使用,如上所述。你可以像这样使用它:
或者,您可以使用
OSAllocatedUnfairLock
,它已经是Sendable
:为了完整起见,其他替代方案包括原子或UUID。