Clean • Professional
The volatile keyword in Java is used in multithreaded programming to ensure visibility of shared variables across threads.
It guarantees that when one thread updates a variable, all other threads immediately see the updated value.
volatile in Java?In Java, each thread may keep a local cached copy of variables (CPU cache / thread working memory) for performance reasons.
Because of this, a change made by one thread may not be visible to other threads immediately.
👉 The volatile keyword solves this visibility problem.
Definition :
A variable declared as
volatileis always read from and written to main memory, not from a thread’s local cache.
volatilebooleanrunning=true;
volatile Needed?Without volatile:
Example Problem (Without volatile)
classSharedFlag {
booleanrunning=true;
}
running = falsevolatile Works (Internals)The volatile keyword provides the following guarantees:
1. Visibility Guarantee
2. Happens-Before Relationship
3. No Instruction Reordering

volatile Does NOT DoVery important limitations:
synchronized or locksIncorrect Usage Example
volatileintcount=0;
count++;// NOT thread-safe
count++ is a read–modify–write operation and can still cause race conditions.
Correct Usage Example
classVolatileExample {
privatevolatilebooleanrunning=true;
publicvoidstop() {
running =false;
}
publicvoidrun() {
while (running) {
// do work
}
System.out.println("Stopped safely");
}
}
stop()running = false| Feature | volatile | synchronized |
|---|---|---|
| Purpose | Ensures visibility and ordering of shared variables | Ensures mutual exclusion, visibility, and atomicity |
| Visibility Guarantee | Changes made by one thread are immediately visible to others | Visibility guaranteed on entering and exiting synchronized code |
| Atomicity | Does not guarantee atomicity for compound operations | Guarantees atomic execution of the entire block or method |
| Mutual Exclusion | Multiple threads can access simultaneously | Only one thread can execute at a time |
| Locking Mechanism | No locking involved | Uses intrinsic (monitor) lock |
| Thread Blocking | Threads never block | Threads may block while waiting for lock |
| Instruction Reordering | Prevents reordering of volatile reads/writes | Prevents reordering within synchronized boundaries |
| Compound Operations | Not safe for read–modify–write operations | Safe for all compound operations |
| Multiple Variables Safety | Cannot maintain consistency across multiple variables | Can protect multiple shared variables together |
| Granularity | Fine-grained (single variable) | Method-level or block-level |
| Performance Overhead | Very low | Higher due to locking and context switching |
| Scalability | Scales well with high read concurrency | Lower scalability under heavy contention |
| Typical Use Case | State flags, status indicators, configuration values | Critical sections, shared mutable state, consistency |
| Aspect | volatile | Atomic Classes (AtomicInteger, AtomicLong, etc.) |
|---|---|---|
| Primary Purpose | Guarantees visibility and ordering of a variable | Guarantees visibility and atomicity of operations |
| Atomic Operations | Does not support atomic read–modify–write | Supports atomic operations like incrementAndGet() |
| Visibility Guarantee | Updates are immediately visible to other threads | Same visibility guarantees as volatile |
| Thread Safety | Not safe for compound operations | Fully thread-safe for single-variable operations |
| Lock Usage | No locks | No locks (lock-free) |
| Underlying Mechanism | JVM memory barriers | CAS (Compare-And-Set) at CPU level |
| Blocking Behavior | Non-blocking | Non-blocking |
| Performance | Extremely fast | Very fast, slightly slower due to CAS retries |
| Behavior Under Contention | No protection; race conditions possible | Handles contention via CAS retries |
Compound Operations (++, --) | Unsafe | Safe |
| Multiple Variable Consistency | Cannot coordinate multiple variables | Limited to single variable |
| Instruction Reordering | Prevents reordering of reads/writes | Prevents reordering |
| Correctness Under Concurrency | Can produce incorrect results | Correct results guaranteed |
| Memory Footprint | Minimal | Slightly higher |
| Ease of Use | Very simple | Simple, method-based API |
| Scalability | Best for read-heavy state | Scales well under moderate contention |
| Typical Use Case | Flags, status indicators, configuration | Counters, metrics, accumulators |
Correct Alternative for Counters
import java.util.concurrent.atomic.AtomicInteger;
class Counter {
private AtomicInteger count = new AtomicInteger(0);
public void increment() {
count.incrementAndGet(); // atomic operation
}
public int getCount() {
return count.get();
}
}
volatileUse volatile when:
Common Use Cases
volatile when:👉 Use synchronized, Lock, or Atomic classes instead.
classServer {
privatevolatilebooleanshutdown=false;
publicvoidstart() {
while (!shutdown) {
// accept requests
}
}
publicvoidstop() {
shutdown =true;
}
}
Think of volatile as a shared notice board:
👉 Visibility is guaranteed, but race conditions are still possible.
count++ are not thread-safe.