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