Data Race and Synchronization
A data race appears when multiple threads update shared state without coordination, and synchronization primitives prevent those lost updates.
Concurrency bugs are often hidden inside one innocent-looking line of code.
The statement count = count + 1 feels atomic at the source level, but the runtime performs it as separate read, compute, and write steps. In shared memory, those substeps can interleave unless a synchronization primitive prevents it.
When to reach for this
Reach for this concept when multiple threads read and write the same variable or when a program behaves nondeterministically under load.
Why this matters
Data races are some of the hardest bugs to reproduce because timing changes the result. Synchronization exists to turn timing-sensitive behavior back into deterministic behavior.
The mental model
Races are about interleaving
A race appears when one thread observes or overwrites state in the middle of another thread's update sequence.
Synchronization protects critical sections
Locks and similar primitives make a vulnerable read-modify-write sequence behave as one serialized unit.
Step through the concept
How to use this page
Follow the animation one state at a time and connect the code to the runtime behavior.
- Run the race tab first and watch both threads read the same stale value.
- Then run the lock tab and notice how waiting is what restores correctness.
- Focus on the read-modify-write sequence because that is the real unit that must be protected.
// Thread 1 and Thread 2 both run this count = count + 1
The shared counter behaves differently only because the interleaving changes
| Aspect | Unsynchronized | Synchronized |
|---|---|---|
| Access pattern | Threads interleave freely | Critical section is serialized |
| Correctness | Lost updates possible | Each increment preserved |
| Main tradeoff | More parallelism, less safety | More safety, less concurrency in the critical section |
The short version
- count = count + 1 is not atomic unless the language or hardware makes it atomic.
- Data races happen because threads interleave the read, compute, and write steps.
- Synchronization protects the critical section by forcing a safe order.
- Correct concurrent code is mostly about controlling timing and shared access.