liveBook · Manning

Race condition

As explained in Functional Design and Architecture: Examples in Haskell

A race condition is a concurrency defect in which the outcome depends on an unexpected competition between threads for a shared resource.

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

How Functional Design and Architecture: Examples in Haskell covers it

How deep it goes
Explains interleavings through a meteor-channel failure and contrasts mutexes, concurrent structures, MVar synchronization, and STM transactions.
Examples
Uses meteor reporting and parallel tests sharing an IORef to demonstrate lost, duplicated, and order-dependent results.
What it assumes
Assumes familiarity with threads and mutable state while defining the concurrency failures caused by their interaction.
What you can do after
Diagnose/debug with it by recognizing unsafe shared read-modify-write sequences and selecting synchronization or STM-based state updates.
How it connects
Connects shared mutable state with deadlock, livelock, thread starvation, MVar, STM, IORef, TVar, and test isolation.

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 Functional Design and Architecture: Examples in Haskell. The section links point to the parts of the book it draws on.