[concurrency-interest] question the about the JMM

Jeremy Manson jmanson at cs.umd.edu
Fri Dec 7 03:31:31 EST 2007


Larry Riedel wrote:
>> To me, cache coherence is a protocol used by a processor
>> to address the consistency of its caches.  It defines the
>> behavior of reads and writes to the same memory locations.
> 
> That sounds like a pretty good description to me.  I
> think I might just change "a processor" to "a set of
> threads", and "memory locations" to "sets of objects".

Not really.  A cache coherence protocol is for hardware, not a 
programming language.  See below.

>> [p==q]
>> Thread 1:
>>     r1 = p.x;
>>     r2 = q.x;
>>     r3 = p.x;
>> Thread 2:
>>     q.x = 1;
>>
>> This code reads and writes to memory locations, and
>> therefore relies on a cache coherence protocol.  Its
>> behavior under the Java memory model is different from
>> its behavior under any sane cache coherence protocol.
> 
> The code is not utilizing any inter-thread relative
> ordering constraint mechanisms of the protocol, so
> I think the cache coherence protocol is agnostic
> about whether Thread1 sees r1==r3==0 and r2==1.
> If "x" is volatile though, I would expect the cache
> coherence protocol to make sure r3==1 if r2==1.

So, something which I am not sure I am communicating effectively: all 
stores and loads in Java, regardless of whether they imply a 
happens-before ordering between different threads, have a behavior which 
can be described by the JMM.  All stores and loads executed directly on 
any modern processor have a behavior which can be described by the cache 
coherence protocol, regardless of whether they use atomic operations or 
memory fences / barriers.

The JMM controls what behaviors are allowed by a Java program.  The 
cache coherence protocol controls what behaviors are allowed by 
instructions executing on the hardware.  These are not the same things. 
  Sometimes the JMM makes more guarantees, and sometimes it makes fewer.

(The JMM can make more guarantees because it sometimes inserts explicit 
memory coherence operations where they would not obviously be indicated 
by the code.)

In this case, were these threads executed directly on x86 hardware 
(changing everything to appropriate x86 assembly instructions), without 
any reordering by the compiler, the x86 memory consistency model and 
cache coherence protocol would ensure that that result did not occur.

However, the JMM allows that result, because it allows the compiler to 
reorder the operations.

It's worth repeating this: The JMM controls what behaviors are allowed 
by a Java program.  The cache coherence protocol controls what behaviors 
are allowed by instructions executing on the hardware.  These are not 
the same things.  Sometimes the JMM makes more guarantees, and sometimes 
it makes fewer.

>>> What would be a good example where there is a
>>> happens-before but still r1==r3==0 and r2==1?
>> If you are looking for an example where happens-before
>> edges differ from explicit memory barriers,
> 
> An example where there is a happens-before but still
> r1==r3==0 and r2==1, or something conceptually analogous.
> 
>> edges differ from explicit memory barriers, that's a
>> different question.  It's also a question that doesn't
>> really have an answer, because you really can't map
>> anything to a "memory barrier" in Java, because the
>> notion doesn't exist.
> 
> I did not say anything about "memory barrier", so I am
> ok with the idea that the notion does not exist. (-:

Memory barriers are how you ensure cache coherence at the machine level 
(although there are some other operations which provide certain 
guarantees).  I don't actually know what you mean by using a cache 
coherence protocol without using some sort of cache coherence operation.

As "happens-before" doesn't exist as a concept for cache coherence 
protocols, "memory barriers" don't exist as a concept in Java.


>> An example would be that this:
>>    synchronized (new Object()) {
>>       x = 1;
>>    }
>> Does not have the same memory semantics as this:
>>    mfence;  // or whatever you want to use
>>    x = 1;
>>    sfence;
>>
>> Because synchronization on an Object that can't be
>> accessed by multiple threads can be removed entirely.
> 
> Guessing what role "mfence" and "sfence" are playing
> there, I imagine I might want to use more like:
> 
>     Object o = new Object();
>     mfence(o);
>     x = 1;
>     sfence(o);
> 
> Presuming no reference to "o" leaks out via [ms]fence,
> I would not expect the cache coherence protocol to need
> to impose any actual ordering constraints,

That doesn't really make any sense with respect to memory fences.  They 
are cache coherence operations; they don't have anything to do with a 
given object.

A good, albeit aging, primer on memory consistency is Shared Memory 
Consistency Models: A Tutorial, by Sarita Adve and Kourosh Gharachorloo. 
  It can be found here: http://citeseer.ist.psu.edu/adve95shared.html .

					Jeremy


More information about the Concurrency-interest mailing list