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

Yuval Shavit yshavit at akiban.com
Mon Apr 25 15:50:09 EDT 2011


Your exact use case (the second one) hung for me after a few tries. I ran
"for i in {1..50}; do echo $i; java VolatileTest; done" and it failed on the
13th try. Setting sync=true in t1 caused immediate termination in all the
several-hundred runs I tried, as expected.

On Mon, Apr 25, 2011 at 3:35 PM, Attila Szegedi <szegedia at gmail.com> wrote:

> 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.
>
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20110425/649ca78a/attachment.html>


More information about the Concurrency-interest mailing list