Java / Java 21 Interview Questions
What does the 'volatile' keyword guarantee in Java's memory model?
The volatile keyword provides two guarantees in the Java Memory Model (JMM): visibility and ordering.
- Visibility: A write to a volatile variable is immediately flushed to main memory, and a read of a volatile variable always reads from main memory — not from a CPU cache. This prevents a thread from seeing a stale cached value written by another thread.
- Ordering: volatile establishes a happens-before relationship. All writes performed before a volatile write are visible to any thread that subsequently reads that volatile variable.
// Without volatile — Thread B may never see the update from Thread A
class BadFlag {
boolean running = true; // may be cached in Thread A's register
void stop() { running = false; }
void work() { while (running) { /* spin */ } }
}
// With volatile — Thread B sees the write immediately
class GoodFlag {
volatile boolean running = true;
void stop() { running = false; } // flushed to main memory
void work() { while (running) { /* spin */ } } // reads main memory
}
// volatile is NOT atomic for compound operations
volatile int counter = 0;
counter++; // NOT atomic: read + increment + write — use AtomicInteger
// Double-checked locking with volatile (Java 5+ safe)
class Singleton {
private static volatile Singleton instance;
public static Singleton getInstance() {
if (instance == null) { // first check — no lock
synchronized (Singleton.class) {
if (instance == null) { // second check — locked
instance = new Singleton(); // volatile ensures ordering
}
}
}
return instance;
}
}volatile is weaker than synchronized (no mutual exclusion) but cheaper. Use it for single-variable state flags and simple publish/read patterns. For compound operations (increment, compare-and-swap), use java.util.concurrent.atomic.AtomicInteger and friends.
More Related questions...