Answer
volatile vs synchronized in Java
Both deal with multi-threading, but solve different problems.
volatile Keyword
- ✓Guarantees visibility — changes to a volatile variable are immediately visible to all threads
- ✓Does NOT guarantee atomicity — compound operations (i++) are not thread-safe with volatile
- ✓No locking — threads do NOT block
Java
public class Counter {
private volatile boolean running = true; // visible to all threads immediately
private volatile int count = 0; // reads/writes are atomic for primitives
public void stop() {
running = false; // immediately visible to other threads
}
public void run() {
while (running) { // sees latest value of running
// do work
}
}
}
volatile is Enough When:
- ✓You have a flag (boolean) that one thread writes and others read
- ✓Variable is read/written independently (not compound operation)
Java
// CORRECT: single write, multiple reads — volatile is sufficient
private volatile boolean shutdownRequested = false;
public void shutdown() { shutdownRequested = true; }
public boolean isDone() { return shutdownRequested; }
synchronized Keyword
- ✓Guarantees both visibility AND atomicity (mutual exclusion)
- ✓Only one thread enters a synchronized block at a time
- ✓Other threads block and wait
Java
public class SafeCounter {
private int count = 0;
// synchronized — only one thread increments at a time
public synchronized void increment() {
count++; // read + increment + write = compound operation — needs sync
}
public synchronized int getCount() {
return count;
}
}
Why volatile is NOT Enough for count++
Java
// count++ is NOT atomic — it's three operations:
// 1. read current value of count
// 2. add 1
// 3. write back the new value
// Two threads can read 5 simultaneously, both write 6 → count = 6 instead of 7!
private volatile int count = 0; // ⚠️ still broken for count++
Direct Comparison
| Feature | volatile | synchronized |
|---|---|---|
| Visibility | Yes | Yes |
| Atomicity | No | Yes |
| Performance | Fast (no locking) | Slower (blocks) |
| Use for | Flags, status | Counters, compound actions |
| Blocks threads | No | Yes |
Better Alternatives — java.util.concurrent.atomic
Java
// AtomicInteger — atomic operations without explicit locking
private AtomicInteger count = new AtomicInteger(0);
public void increment() {
count.incrementAndGet(); // atomic: read + increment + write
}
public int getCount() {
return count.get();
}
// Other atomic operations
count.compareAndSet(expected, newValue);
count.addAndGet(delta);
count.getAndSet(newValue);
Practical Example
Java
public class SharedState {
// volatile — flag that signals all threads to stop
private volatile boolean stopRequested = false;
// synchronized — compound operation on shared counter
private int taskCount = 0;
private final Object lock = new Object();
public void requestStop() {
stopRequested = true; // volatile write — all threads see immediately
}
public boolean isStopRequested() {
return stopRequested; // volatile read
}
public void incrementTaskCount() {
synchronized (lock) {
taskCount++; // compound — needs synchronization
}
}
public int getTaskCount() {
synchronized (lock) {
return taskCount;
}
}
}
