Causality in JMM seems to be the most confusing part of it. I have a few questions regarding JMM causality, and allowed behaviors in concurrent programs.
As I understand, the current JMM always prohibits causality loops. (Am I right?)
Now, as per the JSR-133 document, page 24, Fig.16, we have an example where:
Initially x = y = 0
Thread 1:
r3 = x;
if (r3 == 0)
x = 42;
r1 = x;
y = r1;
Thread 2:
r2 = y;
x = r2;
Intuitively, r1 = r2 = r3 = 42
seems impossible. However, it is not only mentioned as possible, but also 'allowed' in JMM.
For the possibility, the explanation from the document which I fail to understand is:
A compiler could determine that the only values ever assigned to
x
are 0 and 42. From that, the compiler could deduce that, at the point where we executer1 = x
, either we had just performed a write of 42 tox
, or we had just readx
and seen the value 42. In either case, it would be legal for a read ofx
to see the value 42. It could then changer1 = x
tor1 = 42
; this would allowy = r1
to be transformed toy = 42
and performed earlier, resulting in the behavior in question. In this case, the write toy
is committed first.
My question is, what kind of compiler optimization is it really? (I am compiler-ignorant.) Since 42 is written only conditionally, when the if
statement is satisfied, how can the compiler decide to go with the writing of x
?
Secondly, even if compiler does this speculative optimization, and commits y = 42
and
then finally makes r3 = 42
, isn't it a violation of causality loop, since there is no cause and effect distinction left now?
In fact there is one example in the same document (page 15, Figure 7) where a similar causal loop is mentioned as unacceptable.
So how come this execution order is legal in JMM?