Computing Library › HPC & Compute
HPC & Compute

Race Conditions

A race condition arises when the result of concurrent operations depends on their timing, producing intermittent, hard-to-reproduce bugs.

When timing decides the answer

A race condition occurs when two or more threads access shared data concurrently, at least one writes, and the outcome depends on the order in which their operations happen to interleave. Because that order varies from run to run, the bug appears intermittently and often vanishes under a debugger, making races among the hardest defects to find.

The classic example

Kronos motion — reaching conditions

Consider two threads each doing counter = counter + 1. This is really three steps: read counter, add one, write it back. If both read the same value before either writes, one increment is lost. The final count is nondeterministic, sometimes correct, sometimes short, depending purely on timing.

Preventing races

The cost of protection

Synchronization prevents races but serializes access, so heavily contended locks become bottlenecks. The best defense is design: minimize shared mutable state, give each thread its own working data, and combine results only at coordination points. This avoids both the bug and the contention it invites.

Detection

Dynamic race detectors (such as ThreadSanitizer) instrument a program to flag conflicting unsynchronized accesses, and are far more reliable than testing alone, since a race may not manifest in most runs. In distributed code the analogue is a message-ordering bug; disciplined use of synchronization and clear ownership of data prevents both.