Definition
The volatile keyword in Java is a mechanism that helps achieve visibility of changes to variables across multiple threads. When a variable is declared volatile, it means:
- No caching: Threads read the value of the volatile variable directly from the main memory rather than from their thread-local cache.
- Happens-before guarantee: Any write to a volatile variable happens before any subsequent read of that variable.
Example
class VolatileExample {
private static volatile boolean flag = false;
public static void main(String[] args) throws InterruptedException {
Thread writerThread = new Thread(() -> {
try {
// Simulate some processing before setting the flag
Thread.sleep(1000);
flag = true;
System.out.println("Flag set to true by writer thread");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread readerThread = new Thread(() -> {
while (!flag) {
// Loop until flag is true
}
System.out.println("Flag is now true in reader thread");
});
writerThread.start();
readerThread.start();
writerThread.join();
readerThread.join();
}
}
Output
Flag set to true by writer thread
Flag is now true in reader thread
Feature
- Changes made to a volatile variable are visible to all threads immediately.
- Ensures that reads and writes to volatile variables happen in a predictable order.
- Unlike synchronized, volatile does not introduce locking, meaning it doesn’t block other threads but offers better performance for certain scenarios.
- It does not guarantee that compound actions (like incrementing a value) are thread-safe.
Advantages
- It is lighter than using synchronized blocks, as it does not involve locking.
- Ensures that all threads have the most up-to-date value of a shared variable, preventing data inconsistency issues.
- Useful in cases where variables are frequently read but rarely updated, providing better performance compared to locks.
- Ideal for use-cases like status flags (running, isActive, etc.) where visibility is more critical than atomicity.