What is the volatile keyword, and how does it differ from synchronized?

9 minadvancedvolatilesynchronizedmemory-visibility

Quick Answer

volatile guarantees visibility — every read of a volatile variable sees the most recent write from any thread, and the compiler/CPU won't reorder it in ways that break that guarantee — but it does not provide atomicity or mutual exclusion for compound operations like increment. synchronized provides both visibility and atomicity/mutual exclusion for an entire critical section, at a higher performance cost.

Detailed Answer

Both relate to thread visibility of shared state, but solve different problems:

volatile guarantees:

  • Visibility: a write to a volatile field is immediately visible to all other threads' subsequent reads (it's flushed to/read from main memory rather than a per-CPU cache, roughly speaking).
  • Ordering: prevents the compiler/JIT/CPU from reordering instructions around the volatile access in ways that would break the visibility guarantee.

It does not guarantee atomicity for compound operations:

volatile int counter = 0;
counter++; // NOT atomic — read, increment, write are 3 separate steps
           // two threads can interleave and lose an increment

synchronized guarantees both visibility (via happens-before on lock acquire/release) and atomicity/mutual exclusion — only one thread executes the guarded block at a time, so compound operations like counter++ are safe if wrapped in it:

synchronized (lock) {
    counter++; // atomic with respect to other threads using the same lock
}

When volatile is enough: simple flags or single-write-many-read state where you don't need atomic compound updates — e.g., a volatile boolean shutdownRequested flag checked by a worker loop.

When you need synchronized (or java.util.concurrent.atomic classes): anything involving read-modify-write sequences (counters, "check-then-act" logic) where multiple threads might interleave mid-operation.

volatile is also cheaper — it has no lock acquisition/contention overhead, just a memory barrier — but that only matters if it actually fits the visibility-only use case.