1

I have encountered the following claim: "Reading or writing to a volatile variable imposes a memory barrier in which the entire cache is flushed/invalidated."

Now consider the following execution scenario:

initial volatile boolean barrier;
initial int b = 0;

thread 1 b = 1; // write1
thread 1 barrier = true; // write2
thread 2 barrier = true; // write3
thread 2 print(b); // r1

Question: is thread 2 guaranteed to print 1?

Based on the claim, I would answer yes: thread 1 flushes its cache on write2 (so that b = 1 ends up in main memory), and thread 2 invalidates its cache on write3 (so that it will read b from main memory).

However, in the relevant JLS sections I am unable to find a guarantee for this behaviour, since write3 is a write, and not a read. Thus the following seemingly crucial clause does not apply:

A write to a volatile variable v (§8.3.1.4) synchronizes-with all subsequent reads of v by any thread (where "subsequent" is defined according to the synchronization order).

Is there some other information I am missing, or am I perhaps misunderstanding something?

(Relevant questions:

Community
  • 1
  • 1
Roy
  • 111
  • 2
  • 2
    How would you ensure that the `write3` in thread 2 happens after `write1` in thread1? If you can ensure that the writes happen in that order then I guess `b == 1` would be seen in thread 2. – jepio Jan 14 '15 at 00:04
  • @jepio: I did not mean to ensure anything - merely describe a possible execution scenario. In that case, then, would it not be possible for thread 2 to read a cached/stale value for b? – Roy Jan 14 '15 at 00:47

2 Answers2

0

I think, you highlighted a wrong word in the phrase you quoted (I mean, the fact that it synchronizes with reads is by far not the main issue here): "A write to a volatile variable v (§8.3.1.4) synchronizes-with all subsequent reads of v by any thread". Note that it does not say anything at all about reads of other variables. Thread-1's version of b might still be sitting in the register for all you know.

Dima
  • 39,570
  • 6
  • 44
  • 70
  • "Thread-1's version of b might still be sitting in the register for all you know." Would this contradict the claim I opened my question with, given the execution? – Roy Jan 14 '15 at 00:45
0

Reasoning of volatile in terms of cache flushing/invalidation will lead to more confusion and it doesn't present the full picture.

A write to a volatile variable v (§8.3.1.4) synchronizes-with all subsequent reads of v by any thread (where "subsequent" is defined according to the synchronization order).

volatile write of variable followed by a read of that variable in other thread establishes a weaker consistency in terms of happens before gaurantee.

i.e changing a little in op code

thread 1 b = 1; // write1
thread 1 barrier = true; // write2
thread 2 while(!barrier) // read barrier
thread 2 print(b); // r1

now it is guaranteed to print b as 1.

Now if you see when thread 2 reads barrier as true and then thread 2 is guaranteed to see everything which happened before writing to barrier in program order.

If you need to see volatile in terms of barrier then please refer http://gee.cs.oswego.edu/dl/jmm/cookbook.html.

In brief volatile implementation invoke two kinds of things first compiler is restricted in what can be optimize w.r.t to volatile read and write. Secondly and more importantly it is implemented

    as volatile read -> loadload 
       volatile wtire - > storeStore|loadStore  
before write and StoreLoad after write.

here loadload means process the invalidate queue before reading the next value ensures reading lates values. StoreStore means flush store buffer before writing the next value.

http://gee.cs.oswego.edu/dl/jmm/cookbook.html. http://www.puppetmastertrading.com/images/hwViewForSwHackers.pdf

veritas
  • 2,444
  • 1
  • 21
  • 30