Wednesday, August 20, 2014

Java volatile keyword by example

    Volatile keyword seems to be a little bit enigmatic at first glance. It is rather rare to see that keyword on a daily basis. How does it work? What effect can it have on the program execution?
The following experiments were performed on jdk1.8.0_05 and Core i5 (Sandy Bridge) processor under Window 7 system. I have prepared a really simple example:
public class ChangeMe {

 private static long changeMe = 0xDeadBeef;

 public static void main(String[] args) {

  Thread t = new Thread(new Runnable() {
   @Override
   public void run() {
    while (true)
     changeMe = System.currentTimeMillis();
   }
  });
  t.setDaemon(true);
  t.start();

  while (changeMe == changeMe)
   System.out.println(System.currentTimeMillis());
  
 }
}
When you execute that piece of code there is a great chance the program flow will last forever. Well, it can be finished after a couple of seconds but when JVM is warmed up - the program execution will not be stopped. You just need to try a couple of times if you are not lucky.
Now, we can modify that code just a little bit:
public class ChangeMe {

 private static volatile long changeMe = 0xDeadBeef;

 public static void main(String[] args) {

  Thread t = new Thread(new Runnable() {
   @Override
   public void run() {
    while (true)
     changeMe = System.currentTimeMillis();
   }
  });
  t.setDaemon(true);
  t.start();

  while (changeMe == changeMe)
   System.out.println(System.currentTimeMillis());
  
 }
}
The execution is stopped after a few seconds. Thanks to volatile keyword - the memory synchronization is enforced - every thread accessing a volatile field must refresh its own copy of that variable. Otherwise, the thread usually just sees its local copy of a shared variable. There is also one more way to enforce memory synchronization:
public class ChangeMe {

 private static long changeMe = 0xDeadBeef;

 public static void main(String[] args) {

  Thread t = new Thread(new Runnable() {
   @Override
   public void run() {
    while (true)
     changeMe = System.currentTimeMillis();
   }
  });
  t.setDaemon(true);
  t.start();

  while (getChangeMe() == getChangeMe())
   System.out.println(System.currentTimeMillis());
  
 }
 
 private static synchronized long getChangeMe() {
  return changeMe;
 }
}
Synchronized keyword does the same thing as volatile keyword - memory synchronization - but it also enforces exclusivity - it is much stronger keyword than volatile.
I believe this hands-on experience shed some light on the mysterious Java keyword.

1 comment :

  1. "every thread accessing a volatile field must refresh its own copy of that variable" - i have recently came across statement, that when, for example, thread X is accessing volatile variable previously written to by thread Y, all variables visible to thread Y prior to writing to volatile var are now visible for thread X. It does not make much sense for me.

    ReplyDelete