๐ WAYPOINT LESSON
Races & Visibility
โญโญ intermediateโณ 15 min read๐ Lesson 95 of 180
Lost updates, invisible writes, and the volatile โ atomic โ synchronized ladder with when each is correct.
Race conditions and visibility
Two problems plague shared mutable state:
Interference โ count++ is read-modify-write; two threads can read
the same value and lose an increment:
class Counter { int count; void inc() { count++; } }
// 2 threads ร 10_000 increments โ often < 20_000
Visibility โ without synchronization, one thread's writes may never become visible to another (the JIT may hoist the read out of a loop):
boolean stop = false; // plain field โ may never be seen!
// Thread A: while (!stop) work();
// Thread B: stop = true;
Fixes, weakest to strongest:
volatileโ visibility only; fine for flags, wrong for count++AtomicLong/AtomicIntegerโ atomic read-modify-write (incrementAndGet())synchronizedblocks โ mutual exclusion for compound actions
class SafeCounter {
private final AtomicLong count = new AtomicLong();
void inc() { count.incrementAndGet(); }
long value() { return count.get(); }
}
Rule of thumb: make shared state immutable, or confine it to one thread, or protect every access consistently โ pick one and document it.