It is writtem in JLS concerning happens-before relationship of JMM (section 17.4.5):
It should be noted that the presence of a happens-before relationship between two actions does not necessarily imply that they have to take place in that order in an implementation.
I am interested in examples of this statement.
Am I understand this right that as an example of this could be the following:
Thread 1
x = 1
lock M
y = 2
unlock M ----------------------->Thread 2:
lock M
z = 3
w = 4
unlock M
Evidently, in this execution trace there is a happens-before relationship between (x = 1) and (w = 4):
(x = 1) happens-before (w = 4)
Also in this case (x = 1) is ordered with (w = 4) in execution trace.
Thread 1
does not use variable w
. Hence, we can place it before (x = 1) without violating the logic of Thread 1
and Thread 2
.
Does this mean that if we reorder (x = 1) and (w = 4) then happens-before relationship between those statements preserve?
If you have some other examples please provide.
Yes, you're right, happens-before relationship holds when independent data changes. As for other examples, don't forget that happens-before applies to the events in the same thread as well. The rule is very simple:
If x and y are actions of the same thread and x comes before y in program order, then hb(x, y).
So every statement in the Java method happens-before every following statement, but of course JIT-compiler and CPU are free to reorder independent statements (and they are actually doing this quite often to optimize the performance). Sometimes you can observe this reordering from another thread which does not have happens-before relations with current thread.
Thread 1 does not use variable w
You can't assume that this is a reason since actually, the Java Memory Model does not take into account whether it's safe to reorder instructions in a thread isolated context, regarding perception of others involved thread.
Without locking or memory barrier, JMM only guarantees happens-before of statements within the same thread.
In your case, you have a locking mechanism on the same object (M) so the "happens-before" occurs.
synchronized
(locking) or other atomic variables in Java handles memory barrier and atomicity.
For information, volatile
variables and final
variables assignement in constructor only handles memory barrier.
Take this example for instance, dealing with no memory barrier at all:
Class Reordering {
int x = 0, y = 0;
public void writer() {
x = 1;
y = 2;
}
public void reader() {
int r1 = y;
int r2 = x;
}
}
Let's say that this code is executed in two threads concurrently, and the read of y sees the value 2. Because this write came after the write to x, the programmer might assume that the read of x must see the value 1. However, the writes may have been reordered. If this takes place, then the write to y could happen, the reads of both variables could follow, and then the write to x could take place. The result would be that r1 has the value 2, but r2 has the value 0.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With