Data race¶
Category: Hazards · Status: stub · Lessons: chapter 02, Shared state
One line: Two threads access the same memory at the same time, at least one of them writing, with nothing synchronizing them — undefined behaviour in C and C++, a compile error in safe Rust.
Also called: unsynchronized access.
How it connects¶
flowchart LR
n_atomic_variable["Atomic variable"]
n_data_race["Data race"]
n_data_race_freedom["Data-race freedom by construction"]
n_immutability["Immutability"]
n_mutual_exclusion["Mutual exclusion"]
n_race_condition["Race condition"]
n_safety_failure["Safety failure"]
n_send_and_sync["Send and Sync"]
n_shared_memory["Shared memory"]
n_thread_confinement["Thread confinement"]
n_thread_local_storage["Thread-local storage"]
n_atomic_variable -->|prevents| n_data_race
n_data_race ---|vs| n_race_condition
n_data_race -->|is a| n_safety_failure
n_data_race_freedom -->|prevents| n_data_race
n_immutability -->|prevents| n_data_race
n_mutual_exclusion -->|prevents| n_data_race
n_send_and_sync -->|prevents| n_data_race
n_shared_memory -->|can cause| n_data_race
n_thread_confinement -->|prevents| n_data_race
n_thread_local_storage -->|prevents| n_data_race
classDef center stroke-width:3px
class n_data_race center
classDef outside stroke-dasharray: 4 3
class n_atomic_variable,n_data_race_freedom,n_immutability,n_mutual_exclusion,n_race_condition,n_safety_failure,n_send_and_sync,n_shared_memory,n_thread_confinement,n_thread_local_storage outside
- Is a kind of: Safety failure
- Is prevented by: Atomic variable, Data-race freedom by construction, Immutability, Mutual exclusion, Send and Sync, Thread confinement, Thread-local storage
- Can be caused by: Shared memory
- Often confused with: Race condition
- See also: Happens-before, Race detector, Weak memory models and reordering
In each language¶
| Rust | The Rustonomicon ↗: safe Rust guarantees there are none; in unsafe code a data race is undefined behaviour ↗ |
| Go | Compiles and runs: the memory model ↗ requires such access to be serialized and warns that races can corrupt memory; the race detector ↗ (-race) reports them at run time |
| C | Memory model and data races ↗: if a data race occurs, the behaviour of the program is undefined |
| C++ | Multi-threaded executions and data races ↗: a data race is undefined behaviour; std::atomic or a mutex avoids it |
| Java | Not undefined behaviour, but JLS §17.4 ↗ specifies a memory model with few guarantees for unsynchronized reads, and §17.7 ↗ warns that writes to long and double are not atomic |
| Python | In the free-threaded build ↗ built-in types like dict, list and set use internal locks, much as the GIL protected them; the program's own invariants still need threading.Lock |
| JavaScript | Only memory shared through a SharedArrayBuffer ↗ can race; Atomics ↗ operations make its reads and writes predictable |
| Swift | The Swift Programming Language: Concurrency ↗: most data races are compile-time errors, and those found only at run time terminate the program |
Where to read more¶
- In this library: Is total += n safe on two threads?
- In a sibling library: Rust: Data races (for C and C++ programmers) ↗
- In a sibling library: Go: A mutex guards a counter ↗
- In a sibling library: Go: The race detector ↗
- In the books: Rust Atomics and Locks, Mara Bos — ch. 1, 'Basics of Rust Concurrency' → 'Borrowing and Data Races'
- In the books: Concurrency with Modern C++, Rainer Grimm — ch. 13, 'Challenges' → 'Data Races'
- In the books: Mastering C++ Multithreading, Maya Posch — ch. 7, 'Best Practices' → 'Being careless - data races'
- In the books: Parallel Programming with Intel Parallel Studio XE, Stephen Blair-Chappell, Andrew Stokes — ch. 8, 'Checking for Errors' → 'Detecting Data Races'
- In the books: Effective Python, Brett Slatkin — ch. 7, 'Concurrency and Parallelism' → 'Item 54: Use Lock to Prevent Data Races in Threads'
- Reference: Wikipedia: Race condition (data race) ↗