A race condition is a concurrency defect where threads compete unexpectedly over shared mutable state, so the result depends on timing rather than intended logic. It may corrupt data, create invalid state, lose work, or process the same work twice. These failures are difficult because parallel execution defeats ordinary sequential intuition. section 9.1.1
The dangerous shape is usually a multi-step read-modify-write operation: one thread reads shared data, computes an update, and writes it back while another thread can interleave its own read or write. Each individual operation may appear valid, yet their combined ordering is not. Shared mutable structures should therefore be treated as dangerous whenever several threads can access them. section 9.1.1 section 9.1.2
Meteor reporting channel
An astronomer adds a meteor to a shared list while a tracking center reads the list and clears it. If the center clears the channel after an astronomer has read an older version but before that astronomer writes, a report can be lost. Other orderings can make meteorites appear twice. The defect is not a crash; it is invalid output produced by an uncontrolled sequence of otherwise ordinary operations. section 9.1.2
Figure 9.3 Race condition in accessing a shared resource and double-usage error
The interleaving diagram makes the double-usage failure visible: separate reads and writes overlap without a protected ownership boundary. section 9.1.2
Reduce race-condition risk by changing how shared state is handled:
- Synchronize access with a mutex or an MVar so one thread completes its critical work before another operates on the resource. section 9.1.2 section 9.1.4
- Use a concurrent data structure, such as ConcurrentQueue, when it matches the required producer-consumer behavior. section 9.1.2
- Avoid exposing mutable operations that let application logic change limits or state while parallel work relies on earlier values. section 9.1.4
- Move shared updates into STM transactions. A TVar update wrapped with atomically replaces unsafe IORef-style read and write steps with a thread-safe transaction. section 9.2.3
Eliminating mutable sharing is often simpler than coordinating it. Sequential application and process scripts remain thread-safe when no mutability is involved, even if lower-level language actions execute in parallel. Race risks return as soon as shared mutable state or mutable interfaces cross those boundaries. section 9.1.4
Race conditions also occur in tests. Tests that share an IORef can pass in one order and fail when run in parallel because a write from one test races with a read in another. Keep effectful tests isolated, minimize outside interleaving, and separate concerns so test results do not depend on execution order. section 15.1.1



















