The volatile keyword in Java is used to ensure that changes made to a variable are immediately visible to all threads. It is commonly used in multithreading to maintain data consistency without full synchronization.
- Ensures visibility of shared variables across threads by preventing caching issues.
- Does not provide atomicity, so it is not suitable for operations like increment (count++).
Syntax:
volatile dataType variableName;
class SharedData {
volatile boolean flag = false;
}
class MyThread extends Thread {
SharedData data;
MyThread(SharedData data) {
this.data = data;
}
public void run() {
while (!data.flag) {
// waiting
}
System.out.println("Flag changed!");
}
}
public class Geeks{
public static void main(String[] args) throws Exception {
SharedData data = new SharedData();
MyThread t = new MyThread(data);
t.start();
Thread.sleep(1000);
data.flag = true;
}
}
Output:

Explanation:
- The thread keeps running in the while (!data.flag) loop.
- After 1 second, the main thread sets flag = true.
- Because flag is volatile, the change is immediately visible.
- The loop exits, and the message "Flag changed!" is printed.
When to Use volatile
- For boolean flags (e.g., stop thread signal)
- For status indicators
- When only one thread writes and others read
- When no compound operations are involved (like increment)
Volatile vs Synchronized
| Feature | volatile | synchronized |
|---|---|---|
| Purpose | Ensures visibility of variables | Ensures visibility + atomicity |
| Thread Safety | Partial (only visibility) | Full thread safety |
| Atomicity | Not guaranteed | Guaranteed |
| Locking | No locking | Uses intrinsic lock (monitor) |
| Performance | Faster (lightweight) | Slower (due to locking overhead) |
| Use Case | Flags, status variables | Critical sections, shared resources |