Swift には ObjC のatomic
プロパティ属性がないため、Swift クラス用に Swift で「ロック」とそのロックを使用するアトミック プロパティ ラッパーを作成しました。
スレッド サニタイザーを有効にしてテストを実行すると、Atomic プロパティ ラッパーを使用するプロパティでデータ競合が常にキャプチャされます。
機能した唯一のことは、プロパティ ラッパーの宣言を構造体ではなくクラスに変更することでした。ここでの主な問題は、なぜ機能するのかということです。
プロパティ ラッパーに sを追加し、作成されたオブジェクトの数を追跡するために s をprint
ロックinit
しました。構造体/クラスと同じで、別のプロジェクトで問題を再現しようとしましたが、うまくいきませんでした。しかし、問題に似たファイルを追加し、それが機能する理由の推測をお知らせします.
ロック
public class SwiftLock {
init() { }
public func sync<R>(execute: () throws -> R) rethrows -> R {
objc_sync_enter(self)
defer { objc_sync_exit(self) }
return try execute()
}
}
アトミック プロパティ ラッパー
@propertyWrapper struct Atomic<Value> {
let lock: SwiftLock
var value: Value
init(wrappedValue: Value, lock: SwiftLock=SwiftLock()) {
self.value = wrappedValue
self.lock = lock
}
var wrappedValue: Value {
get {
lock.sync { value }
}
set {
lock.sync { value = newValue }
}
}
}
モデル (ここのプロパティでデータ競合が発生するはずです)publicVariable2
class Model {
@Atomic var publicVariable: TimeInterval = 0
@Atomic var publicVariable2: TimeInterval = 0
var sessionDuration: TimeInterval {
min(0, publicVariable - publicVariable2)
}
}
更新 1: 完全な Xcode プロジェクト: https://drive.google.com/file/d/1IfAsOdHKOqfuOp-pSlP75FLF32iVraru/view?usp=sharing