Yesterday, we mentioned Thread Caching, where each thread has its own local cache to store copies of variables. This means that other threads may not immediately see these modifications because they continue to use the old values in their local caches. Now, let’s introduce the concept of volatile
.
volatile
is a modifier used to declare a variable as "mutable." This means its value can be modified by multiple threads simultaneously, and volatile
ensures that these changes are visible to all threads. This is because the value of a volatile
variable is not cached locally but is directly read from and written to the main memory.
Furthermore, because multiple threads continually read variables from the main memory, it can lead to a performance decrease. Also, it’s important to note that volatile
only guarantees visibility and does not ensure atomicity of operations. If multiple threads modify a volatile
variable simultaneously, it may result in a race condition. Achieving atomic operations typically requires the use of the synchronized
keyword.
In summary, volatile
is best suited for scenarios where a single thread writes, and multiple threads only read.
public class VolatileExample {
private volatile boolean flag = false;
public void setFlag() {
flag = true;
}
public boolean isFlag() {
return flag;
}
public static void main(String[] args) {
VolatileExample example = new VolatileExample();
// Thread 1: Set the flag to true
Thread thread1 = new Thread(() -> {
example.setFlag();
System.out.println("Flag set to true.");
});
// Thread 2: Check the flag and perform an action when it's true
Thread thread2 = new Thread(() -> {
while (!example.isFlag()) {
// Wait for the flag to become true
}
System.out.println("Flag is now true, performing an action.");
});
thread1.start();
thread2.start();
}
}