Card 05/ 09

ConceptDifficulty: Advanced1 min

Memory Visibility: What One Thread Can See of Another's Writes

A write that happened, and that another thread may never see, even though nothing interleaved.

Visibility is whether a value one thread writes can be seen by another thread, and when. Without something that forces it, Java does not promise that another thread ever sees a write. That is a second way shared state goes wrong, separate from a race, where two threads interleave in the middle of one update.

A worker loop checks a boolean flag on every pass. Another thread sets the flag to true. The loop keeps going, for minutes, on a value that was changed long ago:

java
class Worker implements Runnable {
    boolean stopped = false;

    public void run() {
        while (!stopped) { doWork(); }
    }

    void stop() { stopped = true; }
}

Nothing interleaved and nothing was lost. The write happened, and it is not visible to the thread that needs it.

Each processor core has its own caches, and the compiler and the processor may both reorder instructions and keep values in registers, as long as a single thread's own view stays consistent. Nothing in that promise says anything about what a second thread sees, or when.

The two failures side by side
Compared onA raceA visibility problem
What went wrongTwo threads interleaved mid-operationA write is not seen by another thread
SymptomA wrong valueA stale value, sometimes forever
Fixed byMaking the operation atomic, so no thread can see it half donePublishing the write
Shows upUnder loadOften only after the code is optimised, during warm-up

So "it works on my machine" is even less reassuring here than usual. A visibility bug often appears only once the virtual machine has decided a loop is hot enough to optimise, well after its first thousand passes.