Istnieje istotna różnica techniczna między warunkami wyścigu a wyścigami danych. Większość odpowiedzi wydaje się przyjmować założenie, że te terminy są równoważne, ale nie są.
Wyścig danych ma miejsce, gdy 2 instrukcje uzyskują dostęp do tego samego miejsca w pamięci, co najmniej jeden z tych dostępów to zapis i przed złożeniem zamówienia między tymi dostępami nie ma miejsca. Teraz to, co dzieje się przed złożeniem zamówienia, jest przedmiotem wielu dyskusji, ale generalnie pary ulock-lock na tej samej zmiennej blokującej i pary sygnał oczekiwania na tej samej zmiennej warunkowej wywołują zdarzenie poprzedzające zamówienie.
Warunek wyścigu jest błędem semantycznym. Jest to usterka występująca w czasie lub porządku zdarzeń, która prowadzi do błędnego zachowania programu .
Wiele warunków wyścigu może być (i faktycznie jest) spowodowanych wyścigami danych, ale nie jest to konieczne. W rzeczywistości wyścigi danych i warunki wyścigu nie są ani koniecznym, ani wystarczającym warunkiem dla siebie nawzajem. Ten post na blogu również bardzo dobrze wyjaśnia różnicę na prostym przykładzie transakcji bankowej. Oto kolejny prosty przykład, który wyjaśnia różnicę.
Teraz, kiedy dopracowaliśmy terminologię, spróbujmy odpowiedzieć na pierwotne pytanie.
Biorąc pod uwagę, że warunki rasowe to błędy semantyczne, nie ma ogólnego sposobu ich wykrywania. Wynika to z faktu, że nie ma możliwości posiadania zautomatyzowanej wyroczni, która w ogólnym przypadku byłaby w stanie odróżnić prawidłowe i niepoprawne zachowanie programu. Wykrywanie rasy jest nierozstrzygalnym problemem.
Z drugiej strony rasy danych mają precyzyjną definicję, która niekoniecznie odnosi się do poprawności, a zatem można je wykryć. Istnieje wiele odmian detektorów wyścigów danych (wykrywanie wyścigów danych statycznych / dynamicznych, wykrywanie wyścigów danych na podstawie lockset, wykrywanie wyścigów na podstawie zdarzeń sprzed zdarzeń, wykrywanie wyścigów hybrydowych). Najnowocześniejszym detektorem dynamicznych wyścigów danych jest ThreadSanitizer, który działa bardzo dobrze w praktyce.
Ogólnie rzecz biorąc, obsługa wyścigów danych wymaga pewnej dyscypliny programistycznej, zanim dojdzie do krawędzi między dostępem do współdzielonych danych (podczas opracowywania lub po ich wykryciu za pomocą wyżej wymienionych narzędzi). można tego dokonać za pomocą blokad, zmiennych warunkowych, semaforów itp. Można jednak zastosować różne paradygmaty programowania, takie jak przekazywanie komunikatów (zamiast pamięci współużytkowanej), które pozwalają uniknąć wyścigów danych przez konstrukcję.