A race condition occurs when the program's behavior depends on the relative timing of events, such as the order in which threads execute.
Thread A: Thread B:
read x (= 0) read x (= 0)
x = x + 1 x = x + 1
write x (= 1) write x (= 1)
Expected: x = 2
Actual: x = 1 ← Lost update!
Both threads read the same initial value, compute independently, and overwrite each other.
| Type | Description |
|---|---|
| Read-Modify-Write | Check-then-act on shared state |
| Check-Then-Act | Condition changes between check and action |
| Compound Operations | Multiple operations that should be atomic |
go run -race or go test -race| Strategy | How |
|---|---|
| Mutex/Lock | Ensure exclusive access |
| Atomic operations | Hardware-level indivisibility |
| Immutability | No shared mutable state |
| Message passing | Actors/channels — no shared memory |
| Thread-local storage | Each thread owns its data |
Bad:
var counter int
func increment() {
counter++ // Race condition!
}