What is a Race Condition
A race condition occurs when two or more threads access shared data without proper synchronization and the result depends on the timing of their execution. The program produces different results depending on which thread runs first — and that order is unpredictable.
How it works
Consider two threads both incrementing a shared counter:
Thread A: read counter (value: 5)
Thread B: read counter (value: 5)
Thread A: write counter (value: 6)
Thread B: write counter (value: 6) // should be 7, but the increment was lost
Both threads read the same value, both compute the same result, and one write overwrites the other. This is a lost update — one of the most common race conditions.
Race conditions are dangerous because they are intermittent. The code may work correctly thousands of times when threads happen to run in a benign order, then fail once when the scheduler interleaves them differently. This makes them notoriously hard to reproduce and debug.
The consequences range from minor (an off-by-one counter) to catastrophic (corrupted data structures, security vulnerabilities, financial losses). The 2003 Northeast blackout was partly attributed to a race condition in monitoring software.
The fix is synchronization. A mutex around the read-modify-write sequence ensures only one thread executes it at a time. Atomic operations (like fetch_add) combine the read and write into a single indivisible step. Some languages prevent data races at compile time — Rust's ownership system makes it impossible to have two mutable references to the same data, catching races before the code even runs.
A data race is a specific kind of race condition: two threads access the same memory location, at least one is a write, and there is no synchronization. In C and C++, data races are undefined behavior.
Why it matters
Race conditions are among the most difficult bugs in software. They are hard to find, hard to reproduce, and hard to prove you've fixed. Understanding them is essential for writing correct concurrent code — and for choosing languages and tools that help prevent them.
See How Threads Work for strategies to avoid race conditions.