Ответ
Требуется синхронизация доступа. Без нее возникает состояние гонки (race condition), приводящее к неопределенному поведению и крашам.
1. Serial DispatchQueue (базовый подход):
let serialQueue = DispatchQueue(label: "com.app.dataQueue", qos: .userInitiated)
private var _counter = 0
var counter: Int {
get { serialQueue.sync { _counter } }
set { serialQueue.async(flags: .barrier) { self._counter = newValue } }
}
// Использование
serialQueue.async {
self._counter += 1
print("Counter: (self._counter)")
}
2. Actor (Swift 5.5+, Concurrency):
actor BankAccount {
private var balance: Decimal = 0
func deposit(amount: Decimal) {
balance += amount
}
func withdraw(amount: Decimal) async throws {
guard balance >= amount else { throw InsufficientFundsError() }
balance -= amount
}
func currentBalance() async -> Decimal {
return balance
}
}
// Использование
let account = BankAccount()
await account.deposit(amount: 1000)
let balance = await account.currentBalance()
3. @Atomic property wrapper (ручная реализация):
import os.lock
@propertyWrapper
struct Atomic<Value> {
private var value: Value
private let lock = os_unfair_lock()
init(wrappedValue: Value) {
self.value = wrappedValue
}
var wrappedValue: Value {
get {
os_unfair_lock_lock(&lock)
defer { os_unfair_lock_unlock(&lock) }
return value
}
set {
os_unfair_lock_lock(&lock)
defer { os_unfair_lock_unlock(&lock) }
value = newValue
}
}
}
// Использование
class SharedData {
@Atomic var counter = 0
@Atomic var configuration: [String: Any] = [:]
}
4. NSLock / NSCondition (Objective-C совместимость):
class ThreadSafeArray<T> {
private var storage: [T] = []
private let lock = NSLock()
func append(_ element: T) {
lock.lock()
defer { lock.unlock() }
storage.append(element)
}
var count: Int {
lock.lock()
defer { lock.unlock() }
return storage.count
}
}
Рекомендации по выбору:
- Actor — для нового кода с async/await
- Serial Queue — для GCD-кода, простые случаи
- @Atomic — для отдельных свойств
- NSLock — при работе с Objective-C кодом
Диагностика: Включите Thread Sanitizer (TSan) в схеме для обнаружения гонок данных.