liveBook · Manning

Race condition

As explained in 100 Go Mistakes and How to Avoid Them

A race condition is a concurrency defect in which program behavior depends on the timing or ordering of operations on shared state.

A race condition is a concurrency defect in which behavior depends on the timing or ordering of events that the program does not control. Goroutine execution order, channel message timing, and database-call duration can all affect the result. section 8.4.1

Do not confuse a race condition with a data race. A data race occurs when goroutines access the same memory location concurrently and at least one access writes. A mutex can remove that data race without making the result deterministic. section 8.4 section 8.4.1

Mutual exclusion does not guarantee order

Two goroutines can lock the same mutex and assign different values: one sets i = 1 and the other sets i = 2. The mutex prevents simultaneous access, but the final value still depends on which goroutine runs last. This is a race condition without a data race. section 8.4.1

i := 0
 
go func() {
    i++       #1
}()
 
go func() {
    i++
}()

Inspect the shared-counter example that exposes concurrent access to the same variable. section 8.4.1

Choose the remedy according to the required guarantee:

  • Use a mutex to protect shared state when mutual exclusion is the needed guarantee, but do not assume it establishes a particular execution order. section 8.4.1
  • Use channels or explicit coordination when operations must happen in a specific sequence or when ownership should pass between goroutines. section 8.4.1

Race conditions can produce subtle or severe failures. Testing may miss them because timing, workload, and execution schedules vary; diagnosing them requires reasoning about both shared memory and event ordering. section 8.4 section 1.3.1

How 100 Go Mistakes and How to Avoid Them covers it

How deep it goes
Explains definitions, interleavings, mutex limitations, and coordination remedies, then defers deeper treatment to the Go memory model.
Examples
Uses shared increments, interleaving tables, mutex-protected assignments, atomic increments, and channel-coordinated updates.
What it assumes
Assumes basic concurrency familiarity while distinguishing data races from race conditions through Go goroutine examples.
What you can do after
Diagnose nondeterministic concurrent behavior and choose atomic operations, mutexes, or channels according to the required guarantee.
How it connects
Connects race conditions with data races, goroutines, mutexes, atomic operations, channels, coordination, and the Go memory model.

Also explained in

Compare how 20 books explain race condition →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of 100 Go Mistakes and How to Avoid Them. The section links point to the parts of the book it draws on.