Java volatile keyword explained by example

Overview

volatile is probably the less known/understood/documented keyword in Java.
I have recently read an article on one of my favourite blog about the volatile keyword. The author shows a piece of code where the volatile keyword seems to have an influence. This example was not easy to understand and the role of the volatile keyword on the behaviour of the JVM was not really defined. So I have decided to browse the web to find a better code example for the volatile keyword. After one hour, nothing! Only wrong examples, articles comparing volatile with synchronized and other confused examples where the author seems as lost as the reader…

Basic Example

The following show a basic example where volatile is required

public class VolatileTest {

    private static volatile int MY_INT = 0;

    public static void main(String[] args) throws InterruptedException
    {
        new ChangeListener().start();
        System.out.println("Waiting two seconds so the JIT will probably optimize ChangeListener");
        Thread.sleep(2000);

        new ChangeMaker().start();
    }

    static class ChangeListener extends Thread {
        @Override
        public void run() {
            int local_value = MY_INT;
            while ( local_value < 5){
                if( local_value!= MY_INT){
                    System.out.println("Got Change for MY_INT : "+ MY_INT);
                     local_value= MY_INT;
                }
            }
        }
    }

    static class ChangeMaker extends Thread{
        @Override
        public void run() {

            int local_value = MY_INT;
            while (MY_INT <5){
                System.out.println("Incrementing MY_INT to " + (local_value + 1));
                MY_INT = ++local_value;
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) { e.printStackTrace(); }
            }
        }
    }
}

With the volatile keyword the output is :
Incrementing MY_INT to 1
Got Change for MY_INT : 1
Incrementing MY_INT to 2
Got Change for MY_INT : 2
Incrementing MY_INT to 3
Got Change for MY_INT : 3
Incrementing MY_INT to 4
Got Change for MY_INT : 4
Incrementing MY_INT to 5
Got Change for MY_INT : 5

Without the volatile keyword the output is :
Incrementing MY_INT to 1
Incrementing MY_INT to 2
Incrementing MY_INT to 3
Incrementing MY_INT to 4
Incrementing MY_INT to 5
.....And the change listener loop infinitely...

Explanation

So what happens? Each thread has its own stack, and so its own copy of variables it can access. When the thread is created, it copies the value of all accessible variables in its own memory. The volatile keyword is used to say to the jvm “Warning, this variable may be modified in an other Thread”. Without this keyword the JVM is free to make some optimizations, like never refreshing those local copies in some threads. The volatile force the thread to update the original variable for each variable. The volatile keyword could be used on every kind of variable, either primitive or objects! Maybe the subject of another article, more detailed…

Never used volatile and never met this problem…

Like all threads issues, it happens under specials circumstances. Really special for this one… My example has big chances to show mainly because the ChangeListener thread is busy, thanks to the loop, and the JVM consider that this thread has no time for updating the local variables. Executing some synchronized methods or adding an other variable which is volatile (or even executing some simple lines of code) could modify the JVM behavior and “correct” this problem…

Should I do a big refactor to identify all variables who needs volatile?

Be pragmatic! If you think your project needs it, do it. I think that the essential is to be aware of that, to know what is the goal of each keyword of the java language in order to take the good decisions.

Please find my source code on my github repository

This entry was posted in Java Core and tagged . Bookmark the permalink.

19 thoughts on “Java volatile keyword explained by example

    • Maybe you added additional System.out.printlns or Logger output, which may trigger the JVM into updating the thread’s stack

      • why does your LOGGER ok, but ours (System.out.printlns or log4j) may trigger the JVM to update the thread’s stack

        • I have updated my code using system.out.println and adding a sleep so it’s more likely that the “volatile effect” occurs. That doesn’t change anything on my machine since it was working before, but it can make differences on other machines.

  1. But after this change it worked…
    public static void main(String[] args) {
    new ChangeListener().start();
    new ChangeListener().start();
    new ChangeListener().start();
    new ChangeListener().start();
    new ChangeMaker().start();
    }
    I think I just made the CPU busy enough to force its threads to use local copy of variable.
    Thanks for your wonderful example :)

  2. Indeed my example could give a different output depending on the machine, the JVM, etc.
    Thanks for your comment!

  3. Hi bro !

    I appreciate your effort for explaining . But I get the same logs with & without volatile . COuld you explain please ? :(

    mine is JDK 6 and I ran on NetBeans

    Thanks !

    • The behaviour of this code really depends on a lot of things which make the JVM do the optimization or not.

      You can try as said in an other comment doing something like :
      new ChangeListener().start();
      new ChangeListener().start();
      new ChangeListener().start();
      new ChangeListener().start();

      Which will make you cpu a bit more busy.

  4. Wow. Every couple of years I would try to read something about volatile variables, but never really understood (or believed) when you WERE and WEREN’T supposed to use them. Bad teachers would regurgitate definitions trying to explain “what the volatile keyword is”, but your article correctly explains “what is the problem we are trying to solve”. By *not working*, your simple example *worked perfectly* in helping me understand when volatile is appropriate. (Maybe I just needed to see a broken example to believe that the problem wasn’t just theoretical).

    Also, a big help was this statement “Without this keyword the JVM is free to make some optimizations, like never refreshing those local copies in some threads.” This statement actually teaches something: it’s not just what your code is doing, but what the JVM is doing.

  5. Thanks for the explaination! I must say this pretty much startled me that changing a variable isn’t by default seen in threads that can access them.

    Played with the code and found that if I add this line to the loop in the listener and remove volatile the change will be seen in the listener thread:
    while (local_value < 5) {
    String s = "" + MY_INT;
    Whereas the change isn't seen when using this code:
    while (local_value < 5) {
    int i = 0 + MY_INT;

    Rather tricky stuff I must say!

  6. I’m not sure where you are getting your info, but great topic.
    I needs to spend some time learning more or understanding more.
    Thanks for fantastic information I was looking for
    this info for my mission.

  7. Using a screwdriver, remove the screws around the inside panel under
    the window you are working with. In law, warranty is an essential aspect of business.
    It avoids expensive remedial costs and preserves the integrity of the timber for long-term
    use.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>