What is volatile keyword in Java: Explanation and Example
volatile keyword is used to mark a variable so that changes to it are immediately visible to all threads. It ensures that the variable's value is always read from and written to main memory, preventing threads from caching it locally.How It Works
Imagine you and your friend are sharing a notebook to write notes. If you both keep copies of the notebook at your desks, you might not see each other's updates right away. The volatile keyword in Java acts like a rule that says "always check the shared notebook directly" instead of looking at your own copy.
In technical terms, when a variable is declared volatile, every read of that variable will get the latest value from the main memory, and every write will be immediately saved to main memory. This prevents threads from using outdated cached values and ensures they see the most recent update.
This is important in multi-threaded programs where different threads might be working with the same variable. Without volatile, one thread might not see changes made by another thread right away, causing bugs.
Example
This example shows two threads updating and reading a volatile variable. The reader thread sees the updated value immediately because of volatile.
public class VolatileExample { private static volatile boolean flag = false; public static void main(String[] args) throws InterruptedException { Thread writer = new Thread(() -> { try { Thread.sleep(1000); // wait 1 second } catch (InterruptedException e) { Thread.currentThread().interrupt(); } flag = true; System.out.println("Flag set to true by writer thread"); }); Thread reader = new Thread(() -> { System.out.println("Reader thread started, waiting for flag..."); while (!flag) { // busy wait } System.out.println("Reader thread detected flag change!"); }); reader.start(); writer.start(); writer.join(); reader.join(); } }
When to Use
Use volatile when you have a variable shared between threads and you want to make sure all threads see the latest value immediately. It is useful for simple flags or status indicators.
For example, it can be used to stop a thread by setting a volatile boolean flag from another thread. It is not suitable for complex operations like incrementing a counter because it does not provide atomicity.
In real-world cases, volatile helps avoid subtle bugs caused by threads working with stale data, especially in concurrent programming.
Key Points
- Visibility:
volatileensures changes are visible to all threads immediately. - No caching: Threads do not cache
volatilevariables locally. - Not atomic: Operations like increment are not safe with
volatilealone. - Simple synchronization: Useful for flags and status variables.