Race Conditions
Unsafe shared mutable state in concurrent contexts.
“Program correctness depends on the relative timing of events.” – Brian Goetz
Signs of Use (Symptoms)
- Random failures under load (“Works on my machine, fails in prod”).
- “Heisenbugs” that disappear when you add logging.
- Shared global variables modified without locks.
Why it is bad (Consequences)
- Data Corruption: Two writers overwrite each other.
- Unpredictability: Bugs are intermittent and hard to reproduce.
Why it happens (Root Cause)
Concurrency is hard. Developers often don’t think about threading.
When it might be okay (Exceptions)
- Never okay if it causes corruption. Always guard shared state.
Explanation
Problem
Two threads read count = 10, both increment, both write 11. Count should be 12.
The Flaw
Read-Modify-Write is not atomic.
Real world analogy
Two cashiers selling the “last” ticket because they both checked inventory before either updated it.
Refactoring Solution
- Atomic Operations: Use
Atomics,AtomicInteger. - Locks/Mutexes: Synchronize access.
- Immutability: Avoid shared mutable state.
- Actor Model: Isolate state per actor.
Pros and Cons (of the Antipattern)
| Pros (Why people do it) | Cons (The price you pay) |
|---|---|
Comparison
- Related Antipatterns: None directly.
- Related Principles: ACID Isolation.
Code example
Typescript
Bad (The Antipattern)
Good (The Fix)