Ответ
Data Race (Гонка данных) — это конкретный, низкоуровневый сценарий, когда два или более потока одновременно обращаются к одной ячейке памяти, и хотя бы один доступ — это запись, без должной синхронизации. Это приводит к неопределенному поведению (undefined behavior) и может вызвать сбои, коррупцию данных или краши.
Race Condition (Состояние гонки) — это более широкое, логическое понятие, когда корректность работы программы зависит от относительного порядка или времени выполнения операций в параллельных потоках. Результат становится непредсказуемым и может быть логически некорректным, даже если технического одновременного доступа к памяти не происходит.
Ключевое отличие: Data Race — это подмножество Race Condition, сфокусированное именно на несинхронизированном доступе к памяти.
Пример Data Race (опасный одновременный доступ):
var counter = 0 // Разделяемая mutable-переменная
DispatchQueue.concurrentPerform(iterations: 1000) { _ in
// МНОГО ПОТОКОВ читают и пишут `counter` без синхронизации
counter += 1 // <- DATA RACE! Операция не атомарна (read-modify-write).
}
// Итоговое значение `counter` может быть меньше 1000.
Решение: Использовать синхронизацию (например, DispatchQueue с барьером, NSLock, os_unfair_lock или атомарные операции).
Пример Race Condition без Data Race (логическая ошибка):
var cachedValue: Int?
var valueIsCalculated = false // Флаг-синхронизация предотвращает Data Race
// Поток A
if !valueIsCalculated {
cachedValue = expensiveCalculation() // (1)
valueIsCalculated = true // (2)
}
// Поток B (выполняется параллельно)
if !valueIsCalculated {
cachedValue = expensiveCalculation() // (3) Может выполниться ПОСЛЕ (1), но ДО (2)!
valueIsCalculated = true
}
// RACE CONDITION: Дорогой расчет может быть выполнен ДВАЖДЫ,
// хотя технической гонки данных за флагом и значением нет.
Решение: Использовать примитивы для однократного выполнения (например, dispatch_once в Objective-C) или более строгую синхронизацию всего блока кода.
Как избежать проблем:
- Для предотвращения Data Race: Используйте синхронизацию (
serial DispatchQueue,locks,actorsв Swift) или immutable данные. - Для предотвращения Race Condition: Проектируйте потокобезопасные интерфейсы, где операции либо атомарны, либо не зависят от порядка выполнения.