Use of Volatile Variable in Java

Category: Java   Tags: Java, Java Thread, Java MultiThread, Thread Synchronization

A volatile variable guarantee the visibility of changes between threads. What it means is that if a thread Thread1 updated some value to a volatile variable, the new value will be visible to another thread Thread2, Thread3 and they will always deal with the latest value of a volatile variable.

A volatile variable is stored in main memory and not in a CPU cache. Therefore whenever you store something to a volatile variable, it will be stored in main memory and whenever you read a volatile variable, it will read it from main memory and not from a CPU cache.

How Java volatile Gives a Visibility Guarantee?

In a multithreaded application, each thread makes a local copy of a variable stored in main memory for some performance reason. A system might have multiple CPU and each CPU might have some thread running on it. Each thread will copy a variable from main memory to CPU cache and will work on it. The problem is that JVM doesn't guarantees that when it will copy the variable from main memory to CPU cache and CPU cache to main memory. Because of this uncertainty a thread will never get the latest updated value of a variable.

Lets understand this with an example, imagine there are two thread, Thread1 and Thread2, both are using a shared object which has a non volatile counter variable:

                            public class SharedCounter {
                                public int counter = 0;
                            }
                          
Use of volatile variable in Java

Thread1 is incrementing the counter and Thread2 is reading the counter. Problem is as variable is non volatile so Thread1 is updating the value of counter in its CPU cache and therefore there is no guarantee that when the latest value of counter will be updated in main memory and hence thread Thread2 will not always read the latest value updated by Thread1.

As you can see that a non volatile variable is not visible across the threads, therefore volatile keyword was introduce. If you make counter volatile the problem will be resolved:

                            public class SharedCounter {
                                public volatile int counter = 0;
                            }
                          

Performance

Writes to volatile variable is more expensive than nonvolatile variables writes because of the memory fencing. Memory fencing is required to guarantee visibility and also cheaper than lock acquisition.

As oppose to locking, volatile operations will never block. If your read operation is more than the write operation, volatile variable reduce the performance cost of synchronization compared to locking.

The Happens-Before Relationship

A happens-before relationship assure that any changes made by one thread will be visible to another thread. Any changes to a volatile variable by one thread is visible to another thread and this is how it establish a happens-before relationship.