Volatile

volatile is keyword used with variable to make sure the value are read from and written to main memory rather than CPU cache.
volatile-java

Ordinary Variables : In a multi-threaded application where the threads operate on non-volatile variables, The variables is copied from the main memory to CPU cache, Now the threads access the memory from the CPU cache rather than main Memory to save time and increase the performance.

When there is more than one thread, then all the threads will access the variables from the CPU cache, which means all the read and the write operation are happening in CPU cache.

Now when one thread makes changes to the variable then it is reflected to the CPU cache, so when other thread reads the value from the CPU it might get updated value and everything is fine and good.

Multi-CPU scenario

There are computers which has more than one CPU, and each CPU has cache, now the ordinary variables will start to create problems.

In Multi-CPU computers each thread may run in different CPUs, which means, that each thread may copy the variables into the CPU cache of different CPUs. volatile-in-multi-cpu-computer

With non-volatile variables there are no guarantees about when the Java Virtual Machine (JVM) reads data from main memory into CPU caches, or writes data from CPU caches to main memory.

Imagine a situation in which two or more threads have access to a shared object which contains a counter variable declared like this:


public class SharedNumberObject {

    public int counter = 0;

}

Now Imagine that, after a operation the value of the counter is increased by thread 1, thread-2 just read the value which got increased by thread-1 from time to time.

Do not forget that thread-1 and thread-2 have different CPU caches, So when thread-1 makes changes to the counter variable, the changes are occurred with CPU cache, and there is no guarantee that every change in CPU cache will be reflected to the Main Memory immediately

the counter variable value in the CPU cache may not be the same as in main memory

So when thread-2 tries to read the updated counter value from the main memory, thread-2 may or may not find the updated value. volatile-value-mismatch-java

The problem with thread-2 not seeing the latest value of a variable because the value of counter has not yet been written back to main memory by another thread-1, this is called a visibility problem.

Visibility Problem: The updates of one Thread-1re not visible to other threads.

Full volatile Visibility Guarantee

If Thread-1 writes to a volatile variable and Thread-2 subsequently reads the same volatile variable, then all variables visible to Thread-1 before writing the volatile variable, will also be visible to Thread-2 after it has read the volatile variable.

If Thread-1 reads a volatile variable, then all variables visible to Thread-1 when reading the volatile variable will also be re-read from main memory.


public class MyTime {
    private int hours;
    private int minutes
    private volatile int seconds;


    public void updateTime(int hours, int minutes, int seconds){
        this.hours  = hours;
        this.minutes = minutes;
        this.seconds   = seconds;
    }
}

In above code, the updateTime() method writes three variables, of which only seconds is volatile.

Here hours, minutes and seconds are visible to the thread.

The full volatile visibility guarantee means, that when a value is written to seconds, then all variables visible to the thread are also written to main memory. which means, that when a value is written to seconds, the values of hours and minutes are also written to main memory.

For reading the value, we can write the following code.


public class MyTime {
    private int hours;
    private int minutes
    private volatile int seconds;

    public int totalSeconds() {
        int total = this.seconds;
        total += minutes * 60;
        total += hours * 60;
        return total;
    }

    public void update(int hours, int minutes, int seconds){
        this.hours  = hours;
        this.minutes = minutes;
        this.seconds   = seconds;
    }
}

Notice the totalSeconds() method starts by reading the value of seconds into the total variable. When reading the value of seconds, the values of minutes and hours are also read into main memory.

Therefore you are guaranteed to see the latest values of seconds, minutes and hours with the above read sequence.

JVM and CPU make re-Ordering

JVM and CPU can re-order the provide statements without affecting the semantics of the program. Re-ordering occurs to in crease the performance and reduce the execution time.

For example: The code that we have provided


int a =0;
int b = 0;

a = a +10;
b = b + 20;

The JM and CPU can re-order code like.


int a =0;
a = a +10;

int b = 0;
b = b + 20;

Instruction reordering create a challenge when one of the variables is a volatile variable


public class MyTime {
    private int hours;
    private int minutes
    private volatile int seconds;


    public void updateTime(int hours, int minutes, int seconds){
        this.hours  = hours;
        this.minutes = minutes;
        this.seconds   = seconds;
    }
}

Once the updateTime() method writes a value to seconds, the newly written values to hours and minutes are also written to main memory. It is good now all the values are into main memory.

But if the JVM reorders the statements like


    public void updateTime(int hours, int minutes, int seconds){
		this.seconds   = seconds;
        this.hours  = hours;
        this.minutes = minutes;
        
    }

The values of minutes and hours are still written to main memory when updateTime() method updates the seconds variable, but seconds variable got updated before updating the values of minutes and hours.

So the new value of the minutes and hours are not made visible to other threads as expected sequence. The logic of the reordered code changed the meaning.

I know, I was not clear, So lets put it in layman terms,
Consider example of human life cycle: Infant was born, we start to crawl in four legs, we walk, we take help of walking stick.

Now JVM comes into your life, and shuffles the sequence like Infant born,we take help of walking stick, we walk, we start to crawl in four legs. SO do you htink this makes any sense? No, Similar way we want something with variable but it changed the sequence of writing to main memory

volatile-human-example-simple-words We will learn, how to handle this issue in next topic.

The Java volatile Happens-Before Guarantee

To address the instruction reordering challenge, the Java volatile keyword provides a happens-before guarantee, in addition to the visibility guarantee.

The happens-before guarantee guarantees that: Consider the below code for the example of before-happens guarantee


private int n = 0;
private volatile int y;
private int m

// original
n = 20 // ordinary
y = 30 //volatile
m = n // ordinary

  • JVM cannot reorder the reading or writing to non-volatile variable to happen after writing to volatile variable, in case there is write statement to volatile variable
  • 
    // JVM reorder
    n = 20 // ordinary
    m = n // ordinary
    y = 30 //volatile
    
    or 
    
    m = n // ordinary
    n = 20 // ordinary
    y = 30 //volatile
    

  • Reading and writing to other variables cannot happen after writing to volatile variable
  • 
    // JVM reorder, NOT POSSIBLE
    y = 30 //volatile
    n = 20 // ordinary
    m = n // ordinary
    

    The reads / writes before a write to a volatile variable are guaranteed to happen before the write to the volatile variable.
  • Notice that it is still possible for e.g. reads / writes of other variables located after a write to a volatile to be reordered to occur before that write to the volatile. Just not the other way around. From after to before is allowed, but from before to after is not allowed.
  • Reading and writing to other variable can only happen after the reading of volatile variable
  • 
    // Original order
    m = n // ordinary
    int c = y // volatile
    n = 30 // ordinary
    
    // JVM reorder
    
    int c = y // volatile
    n= 30 // ordinary
    m = n // ordinary
    
    
    The Original order is will be re-Ordered
    

  • It is possible for reads of other variables that occur before the read of a volatile variable can be reordered( like m ) to occur after the read of the volatile. Just not the other way around. From before to after is allowed, but from after to before is not allowed.
  • 
    // Re Order NOT POSSIBLE
    m = n // ordinary
    n = 30 // ordinary
    int c = y // volatile
    

The above happens-before guarantee assures that the visibility guarantee of the volatile keyword are being enforced

JVM much faster than volatile, so Volatile is Not Always Enough

Even if the volatile keyword guarantees that all reads of a volatile variable are read directly from main memory, and all writes to a volatile variable are written directly to main memory, there are still situations where it is not enough to declare a variable volatile.

In the situation explained earlier, where only Thread 1 writes to the shared counter variable, declaring the counter variable volatile is enough to make sure that Thread 2 always sees the latest written value.

As soon as a thread needs to first read the value of a volatile variable, and based on that value generate a new value for the shared volatile variable, a volatile variable is no longer enough to guarantee correct visibility.

The short time gap in between the reading of the volatile variable and the writing of its new value, creates an race condition where multiple threads might read the same value of the volatile variable, generate a new value for the variable, and when writing the value back to main memory - overwrite each other's values.

The situation where multiple threads are incrementing the same counter is exactly such a situation where a volatile variable is not enough.

if two threads are both reading and writing to a shared variable, then using the volatile keyword for that is not enough. You need to use a synchronized in that case to guarantee that the reading and writing of the variable is atomic.

Reading or writing a volatile variable does not block threads reading or writing. For this to happen you must use the synchronized keyword around critical sections.

As an alternative to a synchronized block you could also use one of the many atomic data types found in the java.util.concurrent package. For instance, the AtomicLong or AtomicReference or one of the others.

In case only one thread reads and writes the value of a volatile variable and other threads only read the variable, then the reading threads are guaranteed to see the latest value written to the volatile variable. Without making the variable volatile, this would not be guaranteed.

The volatile keyword is guaranteed to work on 32 bit and 64 variables.

Few Common Question on Volatile

is volatile atomic in java

The effect of the volatile keyword is approximately that each individual read or write operation on that variable is atomic.

Notably, however, an operation that requires more than one read/write -- such as i++, which is equivalent to i = i + 1, which does one read and one write -- is not atomic, since another thread may write to i between the read and the write.

The Atomic classes, like AtomicInteger and AtomicReference, provide a wider variety of operations atomically, specifically including increment for AtomicInteger.

is volatile variable in java thread safe

Not always.

It's not thread safe if multiple threads are writing and reading the variable. It's thread safe if you have one writer thread and multiple reader threads.

can array be volatile in java

Yes, you can make an array (both primitive and reference type array e.g. an int array and String array) volatile in Java but only changes to reference pointing to an array will be visible to all threads, not the whole array.


protected volatile int[] primes = new int[10];

can a method be volatile in java

NO, only variable can be volatile

can a class be volatile in java

No, only variable can be volatile

why we need volatile in java

Volatile increases the visibility of variable to the threads in multi-thread environments

volatile with singleton in java

Volatile keyword in Java is used as an indicator to Thread that do not cache value of this variable and always read it from main memory.

Using Volatile keyword in Java on variables reduces the risk of memory consistency errors, because any write to a volatile variable in Java establishes a happens-before relationship with subsequent reads of that same variable.

If a variable is not shared between multiple threads no need to use volatile keyword with that variable.

One way to implement Singleton pattern using volatile is given as follows:


public class SingletonVolatile {

    private static volatile SingletonVolatile _instance;

    public static SingletonVolatile getInstance() {
        if (_instance == null) {
            synchronized (SingletonVolatile.class) {
                if (_instance == null)
                    _instance = new SingletonVolatile();
            }
        }

        return _instance;
    }

    public static void main(String[] args) {
        System.out.println(SingletonVolatile.getInstance());
        System.out.println(SingletonVolatile.getInstance());
        System.out.println(SingletonVolatile.getInstance());
    }
}

volatile in java vs synchronization

Use Volatile when you variables are going to get read by multiple threads, but written to by only one thread.

Use Synchronized when your variables will get read and written to by multiple threads.

  • Volatile in java is a keyword which is used in variable declaration only and cannot be used with method. We will get compilation error if using volatile with method.
  • Volatile variables read values from main memory and not from cached data so volatile variables are not cached whereas variables defined inside synchronized block are cached.
  • Volatile variables are lock free which means that it does require any lock on variable or object whereas synchronized requires lock on method or block .
  • Volatile variable can be null whereas we will get NullPointerException in case we use null object.
  • As volatile never acquires any kind of lock ,so it will never create deadlock in program. But in case of synchronized we might end up creating deadlock if synchronization is not done properly.
  • Synchronized keyword may cause performance issue as one thread wait for another thread to release lock on shared object whereas volatile variable is lock free and hence is not much expensive in terms of performance.
  • Using synchronization thread can be blocked when waiting for other thread to release lock but not in the case of volatile keyword.
  • Volatile keyword is suitable When there is an independent value to be share among multiple threads like counter and flag. Whereas synchronization is used in the scenario where we are using multiple variables very frequently and these variables are performing some calculation.
  • threadlocal vs volatile in java

    Both are completely unrelated.

    The ThreadLocal class stores a variable in the Thread object of the current running thread, each thread gets its own copy of ThreadLocal instance, the ThreadLocal instances are not shared among the Threads.

    Volatile keyword instructs the compiler that this variable be accessed/shared across multiple threads

About Author

Myself KarthiQ, I am the author of this blog, I know ways to write a good article but some how I donot have the skills to make it to reach people, would you like help me to reach more people By sharing this Article in the social media.

Share this Article Facebook
Comment / Suggestion Section
Point our Mistakes and Post Your Suggestions

Recent Addition

new tutorial Selenium Online Training : Our next online training course for Selenium with Java starts from 17th December 2018.

You can attend first 3 classes for free, the total course fee is INR 10,000

The course time would be 8.00 PM(IST) for the first three classes

If you are interested to learn, then you can join the course by sending email to chercher.tech@gmail.com

or Register below


 
Join My Facebook Group
Join Group
 
gin/email/app_fb_32_fig_white.png" width="16">Join Group