Re: About the volatile and MESI Protocal

Aleksey Shipilev via Concurrency-interest <[email protected]> Sun, 20 Feb 2022 15:25:44 +0300
Newsgroups gmane.comp.java.jsr.166-concurrency
Message-ID <[email protected]>
On 2/19/22 13:30, Florian Weimer via Concurrency-interest wrote:
> * Nathan Reynolds via Concurrency-interest:
> 
>> Without volatile or fences, JIT is free to hoist the "if (bChanged ==
>> !bChanged)" out of the for loop.  If for some reason JIT decides to not
>> hoist, JIT could also load bChanged into a single register each iteration
>> and then execute "if (bChanged == !bChanged)" using the value in the single
>> register.  On the other hand, if JIT is smart enough, it can get rid of the
>> if statement and block altogether since it can never be true according to
>> the Java Memory Model.  Since this is very unlike a real code scenario, I
>> doubt JIT has been enhanced for this last case.
> 
> I don't think this is a property of the memory model, it merely
> follows from choices Java implementation have made regarding compiler
> barriers for volatile field access.

AFAIU, progress guarantee is where the current memory models, as stated in JLS, is quite murky. This 
one of those abyss-mal places where the longer you look, the creepier it gets. The major problem 
there is tying up both writer and loop-reader into the behavior we intuitively want. It is a real 
hard thing to specify without losing sanity.

You can show the lack of progress guarantees for "while (field) {}" loop executing alone, by the 
virtue of saying "there is an JMM execution that never observes the store to `field`". Note it ties 
up the notion that there is a write to "field", and it is ordered "after" all reads.

AFAICS, the same thing could be said when "field" is volatile: a Sufficiently Smart^W Evil Optimizer 
(tm) can say, "Yes, volatile actions are in total order, and I decide that the order we are dealing 
with in this particular micro-test is where the write to field at the end of that total order; thus 
no reads observe it, and I can yank the field load out of the loop". The totality of synchronization 
order really buys us nothing in this example, except for scaring the less smart/evil optimizers into 
not doing anything that touches synchronization actions.

C/C++ spec talks about progress guarantees, where "Implementations should ensure that all unblocked 
threads eventually make forward progress" and "An implementation should ensure that the last value 
(in modification order) assigned by an atomic or synchronization operation will become visible to 
all other threads in a finite period of time". But AFAIU, "should" = "recommended" in that text. 
Hans Boehm et al. wrote why it is not a hard requirement here:
   http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3152.html

Java makes a significant step towards that by saying that "Opaque" and stronger modes guarantee 
progress, but that again is not part of the formal JLS. See "Opaque mode" properties here:
   http://gee.cs.oswego.edu/dl/html/j9mm.html

-- 
Thanks,
-Aleksey