[concurrency-interest] Volatile access used for observing nonvolatile changes

Attila Szegedi szegedia at gmail.com
Mon Apr 25 15:35:58 EDT 2011


So, I have a coworker who's using access to a volatile field to observe changes to a non-volatile field from a different thread. I tried to dissuade him saying there's no guarantee this should always work, he insists this is a sound practice. I'd be interested in the insight of folks on this list. I whittled it down to a very simple example… First, here's a code example that, quite expectedly, doesn't terminate, as t0 never observes the change made in t1:

public class VolatileTest {
  private boolean data;

  public static void main(String[] args) {
    new VolatileTest().run();
  }
  
  private void run() {
    Thread t0 = new Thread() {
      public void run() {
       while(!data);
      }
    };

    Thread t1 = new Thread() {
      public void run() {
       data = true;
      }
    };
    
    t0.start();
    t1.start();
  }
}

However, adding a volatile variable unrelated to the "data" variable and just reading it from t0 does terminate. Note that the volatile variable was never even written from t1!

public class VolatileTest {
  private boolean data;
  private volatile boolean sync;

  public static void main(String[] args) {
    new VolatileTest().run();
  }
  
  private void run() {
    Thread t0 = new Thread() {
      public void run() {
       while(!data) {
         boolean x = sync;
       }
      }
    };

    Thread t1 = new Thread() {
      public void run() {
       data = true;
      }
    };
    
    t0.start();
    t1.start();
  }
}


I thought there might be a cache granularity issue here, so I replaced "boolean data" with a "boolean[ ] data = new boolean[10*1024*1024], and was setting its last element, but it didn't cause a difference. I tried to find an explanation of this behavior from my understanding of JLS 17.4.4 "Synchronization Order" and clauses around it, but couldn't, specifically since t1 never touches the volatile variable. 

Can someone give me an example where this program would again not terminate - that is, t0 wouldn't observe a change to a non-volatile variable even if it did a read of a volatile variable?

This is happening on a Core 2 Duo CPU with 3MB of L2 cache, on Mac OS X 10.6.7, java is:

java version "1.6.0_24"
Java(TM) SE Runtime Environment (build 1.6.0_24-b07-334-10M3326)
Java HotSpot(TM) 64-Bit Server VM (build 19.1-b02-334, mixed mode)

Thanks for any insights,
  Attila.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20110425/e9a84061/attachment.html>


More information about the Concurrency-interest mailing list