The volatile keyword in Java is used to indicate that a variable's value will be modified by different threads. It ensures that the value of the volatile variable will always be read from the main memory, not from the thread's cache memory. This is important for ensuring visibility of changes made by one thread to other threads.
public class VolatileExample { // Declare a volatile variable private volatile boolean flag = true; public void changeFlag() { // This method is called by one thread to change the value of the flag this.flag = false; System.out.println("Flag has been set to false."); } public void runLoop() { // This method is called by another thread which keeps running until the flag becomes false System.out.println("Waiting for flag to become false."); while (flag) { // Busy wait - the loop will keep running as long as flag is true } System.out.println("Flag is now false, stopping the loop."); } public static void main(String[] args) throws InterruptedException { VolatileExample example = new VolatileExample(); // Thread for running the loop Thread loopThread = new Thread(example::runLoop); // Thread for changing the flag Thread changeFlagThread = new Thread(example::changeFlag); loopThread.start(); Thread.sleep(1000); // Wait for 1 second before changing the flag changeFlagThread.start(); } }
Volatile Variable: The flag variable is declared as volatile. This ensures that any changes made to this variable in one thread are immediately visible to other threads.
changeFlag Method: This method is executed by one thread to change the value of the flag variable. Because flag is volatile, the change will be visible to all other threads immediately.
runLoop Method: This method is executed by another thread. It runs in a loop as long as flag is true. Due to flag being volatile, the thread will see the updated value of flag as soon as it's changed by the changeFlag method and exit the loop.
Threads in main Method: Two threads are created and started. One thread runs the loop, and the other changes the value of the flag. There is a deliberate delay (Thread.sleep(1000)) to ensure that the loop starts running before the flag is changed.
Using volatile is essential in this example to ensure that the change in the flag value made by one thread is visible to the other thread.
Without volatile, there is no guarantee that the thread running the loop would ever see the updated value of the flag due to caching at the thread level, potentially causing an infinite loop.
The volatile keyword prevents such caching and ensures visibility of changes across threads, making it a crucial tool for handling shared mutable data in multithreaded Java applications. This is particularly important in scenarios where the consistency and visibility of data across multiple threads are critical for the correctness of the program.