Skip to content

Race Conditions

A bug whose presence depends on the timing/interleaving of concurrent operations — the umbrella category that data races, lost updates, and check-then-act bugs (already covered in depth in this repo's Shared- Memory Concurrency track) all belong to. This page is the map connecting those specific bug shapes to the general concept, plus detection tooling.

flowchart LR Junior["Junior: race condition vs. data race - the precise distinction"] --> Middle["Middle: the check-then-act race shape"] Middle --> Senior["Senior: why races are nondeterministic and hard to reproduce"] Senior --> Professional["Professional: race detectors - how ThreadSanitizer actually finds races"]
flowchart LR Race["Race condition:\nresult depends on\nTIMING/ORDER"] --> DataRace["Data race: a SPECIFIC\nkind of race - unsynchronized\naccess, >=1 write"] Race --> CheckAct["Check-then-act: another\nSPECIFIC kind - state\nchanges between check\nand act"]

Choose a level

Level Guide You are done when
Junior Race condition vs. data race You can explain why every data race is a race condition, but not every race condition is a data race.
Middle The check-then-act shape You can identify a check-then-act race in code and fix it with an atomic operation.
Senior Why races are hard to reproduce You can explain why a race bug can pass every test and still fail in production.
Professional How ThreadSanitizer finds races You can explain the happens-before-violation detection algorithm race detectors use.

Practice rule

For any shared, mutable state touched by more than one thread, ask: "is every access to this either read-only, or protected by the same synchronization mechanism?" If any access path skips synchronization, you likely have a race condition waiting to manifest under the right timing.