Platinum Partner
java

Threading stories: volatile and synchronized

In my last blog about the volatile modifier I have introduced a little program that illustrates the behaviour of volatile in a Java 6 (26) Hotspot VM. Since that day I had some interesting discussions that I wanted to share in this blog. It adds another valuable insights on the volatile modifier.

Here is my little program, which I have adopted a little to make it easier. My previous example was originally thought as a thread contention example, which will be the topic in one of my upcoming posts.

import java.util.Timer;
import java.util.TimerTask;

public class AnotherVolatileExampleA {

 private volatile boolean expired = false;
 private long counter = 0;
 private Object mutex = new Object();

 private class Worker implements Runnable {
  @Override
  public void run() {
   synchronized (mutex) {
    final Timer timer = new Timer();
    timer.schedule(new TimerTask() {
     public void run() {
      expired = true;
      System.out.println("Timer interrupted main thread ...");
      timer.cancel();
     }
    }, 1000);
    while (!expired) {
     counter++; // do some work
    }
    System.out.println("Main thread was interrupted by timer ...");
   };
  }
 }

 public static void main(String[] args) throws InterruptedException {
  AnotherVolatileExampleA volatileExample = new AnotherVolatileExampleA();
  Thread thread1 = new Thread(volatileExample.new Worker(), "Worker-1");
  thread1.start();
 }
}

Now, this program still behaves similar like the one of my last blog. With volatile in line 6 the result written to the console is:

Timer interrupted main thread ...
Main thread was interrupted by timer ...

Without volatile in line 6 the result is:

    Timer interrupted main thread ...  


One question in a discussion was, why that happens although everything takes place in a synchronized block. The Java VM specification says the synchronized keywork garantees that (less formal!) a variable is written into the memory heap and is read from the memory heap (read here). Now, this is true, but it's missing the point that the thread only needs to read the variable ONCE within a single synchronized block. In the example above the expired variable is read once at the very first while loop. Afterwards the thread does not need to read the variable again. Consider this program:

import java.util.Timer;
import java.util.TimerTask;

public class AnotherVolatileExampleB {

 private boolean expired = false;
 private long counter = 0;
 private Object mutex = new Object();

 private class Worker implements Runnable {
  @Override
  public void run() {
   final Timer timer = new Timer();
   timer.schedule(new TimerTask() {
    public void run() {
     expired = true;
     System.out.println("Timer interrupted main thread ...");
     timer.cancel();
    }
   }, 1000);
   boolean tmpExpired = false;
   while (!tmpExpired) {
    synchronized (mutex) {
     tmpExpired = expired;
    }
    counter++; // do some work
   }
   System.out.println("Main thread was interrupted by timer ...");
  }
 }

 public static void main(String[] args) throws InterruptedException {
  AnotherVolatileExampleB volatileExample = new AnotherVolatileExampleB();
  Thread thread1 = new Thread(volatileExample.new Worker(), "Worker-1");
  thread1.start();
 }
}

  In that case the synchronized block is within the while loop (lines 23-25) and the thread is now forced to re-read the expired variable from the main memory in each loop 'cause synchronized garantees to read from memory once (same applies to Java 5 locks). The result of that program will be as expected from a synchronized block:

Timer interrupted main thread ...
Main thread was interrupted by timer ...

 

Therefore, if you wish to read a variable from memory in a synchronized block (or within a Java 5 lock), remember that the thread only garantees to read the variable once from the memory heap. The volatile modifier, on the other hand, always garantees a "memory heap read" (see here).

From http://niklasschlimm.blogspot.com/2011/10/threading-stories-volatile-and.html

{{ tag }}, {{tag}},

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}
{{ parent.authors[0].realName || parent.author}}

{{ parent.authors[0].tagline || parent.tagline }}

{{ parent.views }} ViewsClicks
Tweet

{{parent.nComments}}