Services

Resources

Company

Race condition

A race condition is a bug where the result of a program depends on timing: which of two concurrent operations happens first. The code passes most runs and fails some, because the scheduler interleaves the operations differently each time. Races are common anywhere goroutines, threads or processes share state.

How it works

Most races hide a step that looks atomic but is not. count++ is three steps: read the value, add 1, write it back. If two goroutines both read 41, both add 1 and both write 42, one increment is lost. A check-then-act sequence, such as "if the seat is free, book it", has the same shape at a larger scale.

For example, two goroutines each run count++ 1,000 times on a shared count with no lock. The answer should be 2,000, but a run can print 1,734 because 266 increments were overwritten. Guarding the increment with a sync.Mutex (mu.Lock(), count++, mu.Unlock()), or using atomic.Int64, makes it 2,000 every time. go test -race catches the original bug and prints WARNING: DATA RACE with the stack of both goroutines.

Why it matters in production

Races pass code review and most test runs, then show up under production load as wrong totals, double bookings or corrupted maps; Go stops the program with fatal error: concurrent map writes when it detects the last one. Run tests with -race in CI, prefer passing data over channels to sharing it, and use database transactions or idempotent writes when the shared state lives outside the process. A data race is one kind of race condition; code with correct locks can still have a check-then-act race.

See also

On the One2N blog

References

  1. Data race detector (Go documentation)

  2. The Go memory model (Go documentation)

Four-panel comic about a race condition: Asha expects two goroutines adding 1,000 each to make 2,000 but gets 1,734; both goroutines read 41 and write 42, so one increment is lost; wrapping count++ in a sync.Mutex gives 2,000 every run; Asha runs go test -race in CI to catch data races early.