ошибка конкурентного доступа к памяти два или несколько потоков читают и изменяют общий ресурс, не используя синхронизацию это вызывает ошибки и непредсказуемое поведение, например появление некорректных данных причина — отсутствие блокировок либо атомарных операций например, два потока одновременно инкрементируют один счётчик без мьютекса результатом становятся нестабильность программы и сложная отладка проблему устраняют с помощью мьютексов, атомарных операций или других средств синхронизации
Что такое Data Race и как привести пример?
ошибка конкурентного доступа к памяти два или несколько потоков читают и изменяют общий ресурс, не используя синхронизацию это вызывает ошибки и непредсказуемое поведение, например появление некорректных данных…
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Что называют Data Race?
- ошибка конкурентного доступа к памяти
- два или несколько потоков читают и изменяют общий ресурс, не используя синхронизацию
- это вызывает ошибки и непредсказуемое поведение, например появление некорректных данных
- причина — отсутствие блокировок либо атомарных операций
- например, два потока одновременно инкрементируют один счётчик без мьютекса
- результатом становятся нестабильность программы и сложная отладка
- проблему устраняют с помощью мьютексов, атомарных операций или других средств синхронизации
Пример:
var counter int
func increment() {
counter++ // неатомарно
}
// два потока вызывают increment() без блокировок
Здесь возможен Data Race, поскольку операция ++ не является атомарной: чтение, увеличение и запись значения могут выполняться вперемешку.
Подробный ответ
Основной ответ
Data race — это ситуация в многопоточной программе, при которой два или более потока одновременно обращаются к одной области памяти без корректной синхронизации, причём хотя бы один из них выполняет запись. Это приводит к неопределённому поведению: программа может работать нестабильно или возвращать неправильные данные. Data race нередко становится источником труднообнаруживаемых ошибок, поскольку проявляется только при определённом порядке выполнения потоков.
Ключевые моменты
- Отсутствие синхронизации: чтобы предотвратить data race, применяют блокировки (mutex, semaphore) либо атомарные операции.
- Непредсказуемость: ошибка возникает не при каждом запуске, поэтому её особенно трудно выявить. Даже внешне корректный результат не означает, что data race отсутствует.
- Различие с deadlock: data race представляет собой конфликт при обращении к данным, тогда как deadlock — взаимную блокировку потоков, из-за которой выполнение останавливается.
Пример
Рассмотрим ситуацию, в которой два потока без синхронизации одновременно увеличивают общий счётчик:
int counter = 0;
void increment() {
counter = counter + 1;
}
Если два потока одновременно выполнят increment(), операции чтения и записи значения counter могут пересечься. Поэтому результатом окажется не 2, а 1: один инкремент будет потерян. Для исправления операцию следует защитить мьютексом или применить атомарный тип, например std::atomic<int> в C++11 и более новых версиях.
Практический контекст
В современных многопоточных приложениях, включая Java concurrency и C++ с threading, предотвращение data race является важной задачей. Во время тестирования обнаружить такие ошибки помогают инструменты ThreadSanitizer и Helgrind. В Java применяются volatile и synchronized, а в C++ — std::mutex и атомарные операции, обеспечивающие безопасный доступ к данным.