[concurrency-interest] Volatile access used for observingnonvolatile changes

David Holmes davidcholmes at aapt.net.au
Mon Apr 25 22:41:28 EDT 2011


It is quite common and accepted practice to use a volatile flag to signal
that other data is ready to be read, but the pattern must be used correctly:

Thread 1: write data
               write flag

Thread 2: read flag
               read data

If the flag is set then the data is valid/available. Of course it is very
easy to use this in such a way that the inherent race conditions causes
semantic failures but that is a different issue. It is never correct to use
a completely unrelated volatile to "guard" access to other data - it must be
a volatile written by the thread writing the data. Ortherwise all you
observe at runtime are the affects of implementation mechanics for volatile
accesses.

In your errant example code, it is quite feasible that the runtime compiler
(eg C2/server compiler in hotspot) will turn the:

   while (!data) { whatever }

into:

  if (!data)
     while(true) { whatever }

David Holmes
  -----Original Message-----
  From: concurrency-interest-bounces at cs.oswego.edu
[mailto:concurrency-interest-bounces at cs.oswego.edu]On Behalf Of Attila
Szegedi
  Sent: Tuesday, 26 April 2011 5:36 AM
  To: concurrency-interest at cs.oswego.edu
  Subject: [concurrency-interest] Volatile access used for
observingnonvolatile changes


  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/20110426/974927fe/attachment.html>


More information about the Concurrency-interest mailing list