Ответ
В Swift с помощью Grand Central Dispatch (GCD) атомарность достигается через серийные очереди или барьеры в конкурентных очередях. Оба подхода гарантируют, что критическая секция выполняется без гонки данных.
1. Использование серийной очереди (проще, но менее гибко)
private let serialQueue = DispatchQueue(label: "com.example.atomic.serial")
private var sharedResource: Int = 0
func updateResource(_ newValue: Int) {
serialQueue.async {
self.sharedResource = newValue
}
}
func readResource() -> Int {
return serialQueue.sync {
return self.sharedResource
}
}
2. Использование барьеров в конкурентной очереди (высокая производительность при чтении)
private let concurrentQueue = DispatchQueue(label: "com.example.atomic.concurrent", attributes: .concurrent)
private var sharedResource: Int = 0
func updateResource(_ newValue: Int) {
// Барьер гарантирует эксклюзивный доступ на запись
concurrentQueue.async(flags: .barrier) {
self.sharedResource = newValue
}
}
func readResource() -> Int {
// Множественные чтения могут выполняться параллельно
return concurrentQueue.sync {
return self.sharedResource
}
}
Ключевые моменты:
- Барьеры (
flags: .barrier) блокируют очередь на время выполнения задачи, обеспечивая атомарность записи. - Серийная очередь выполняет задачи строго последовательно, что также обеспечивает атомарность.
- Для сложных структур данных или Swift 5.5+ рассмотрите использование акторов (actors) как более современной альтернативы.