Существует важное техническое различие между условиями гонки и данными гонки. Большинство ответов, кажется, предполагают, что эти термины эквивалентны, но это не так.
Гонка данных происходит, когда 2 инструкции обращаются к одной и той же ячейке памяти, по крайней мере, один из этих обращений является записью, и до упорядочения среди этих обращений ничего не происходит . То, что представляет собой «событие», происходит до того, как упорядочение является предметом многочисленных споров, но в целом пары «блокировка блокировки» для одной и той же переменной блокировки и пары «сигнал ожидания» в одной и той же условной переменной вызывают порядок «происходит раньше».
Состояние гонки - это семантическая ошибка. Это недостаток, возникающий во времени или порядке событий, который приводит к ошибочному поведению программы .
Многие гонки могут быть (и фактически) вызваны гонками данных, но это не обязательно. Фактически, гонки данных и условия гонки не являются ни необходимым, ни достаточным условием друг для друга. Этот пост в блоге также очень хорошо объясняет разницу на простом примере банковской транзакции. Вот еще один простой пример, который объясняет разницу.
Теперь, когда мы прибегли к терминологии, давайте попробуем ответить на первоначальный вопрос.
Учитывая, что условия гонки - это семантические ошибки, нет общего способа их обнаружения. Это связано с тем, что не существует автоматизированного оракула, который может отличить правильное и неправильное поведение программы в общем случае. Обнаружение гонки - неразрешимая проблема.
С другой стороны, у гонок данных есть точное определение, которое не обязательно связано с корректностью, и поэтому их можно обнаружить. Существует множество разновидностей детекторов гонки данных (статическое / динамическое обнаружение гонки данных, обнаружение гонки данных на основе блокировок, обнаружение гонки данных на основе предшествующих событий, обнаружение гибридной гонки данных). Современным детектором динамических данных является ThreadSanitizer, который очень хорошо работает на практике.
Обработка гонок данных в целом требует некоторой дисциплины программирования, чтобы вызывать непредвиденные границы между обращениями к совместно используемым данным (либо во время разработки, либо после того, как они были обнаружены с помощью вышеупомянутых инструментов). это может быть сделано с помощью блокировок, переменных условий, семафоров и т. д. Однако можно также использовать различные парадигмы программирования, такие как передача сообщений (вместо общей памяти), которые избегают скачки данных по построению.