I would like to associate the above statement with some example code stream.
To understand this, take the class below, which has two fields counter and isActive .
class StateHolder { private int counter = 100; private boolean isActive = false; public synchronized void resetCounter() { counter = 0; isActive = true; } public synchronized void printStateWithLock() { System.out.println("Counter : " + counter); System.out.println("IsActive : " + isActive); } public void printStateWithNoLock() { System.out.println("Counter : " + counter); System.out.println("IsActive : " + isActive); } }
And suppose there are three threads T1, T2, T3 that call the following methods on the same StateHolder object:
T1 calls resetCounter() and T2 calls printStateWithLock() at the same time, and T1 gets a lock
T3 -> calls printStateWithNoLock() after completion of T1
It should be noted that the presence of a relationship between two actions does not necessarily mean that they must be performed in this order in the implementation. If reordering leads to results that are consistent with legal execution, this is not illegal.
and the nearest line says
According to the statement above, this gives the flexibility of the JVM, OS, or underlying hardware to reorder operators in the resetCounter() method. And as T1 launches, it can follow the instructions in the following order.
public synchronized void resetCounter() { isActive = true; counter = 0; }
This inline expression does not necessarily mean that they must be executed in that order in the implementation.
Now, looking at it from the point of view of T2, this reordering has no negative effect, since both T1 and T2 are synchronized on the same object, and T2 is guaranteed to see changes in both fields, regardless of whether the reordering has occurred or not, as it happens - before the relationship. Therefore, the conclusion will always be:
Counter : 0 IsActive : true
It’s like an operator. If reordering leads to results consistent with legal execution, it is not illegal
But look at it from the point of view of T3, while reordering that T3 will see the updated value of isActive as "true but still see the counter value as 100`, although T1 has completed its execution.
Counter : 100 IsActive : true
The next paragraph in the link above clarifies the statement and says that:
More specifically, if two actions share a wait relationship, they do not have to appear in that order for any code with which they do not share a wait relationship. Records in one thread that are in a data race with reading in another thread may, for example, appear out of order for these readings.
In this example, T3 ran into this problem because it has nothing to do - before the relationship with T1 or T2. It is inline with It does not have to appear in this order in any code with which they do not share the relationship between events.
NOTE. . To simplify the case, we have one state-changing thread T1, while T2 and T3 read the state. Maybe,
T1 counter to 0 updates, later
T2 changes isActive to true and sees counter is 0 , after some time T3, which prints the state, can still see only isActive as true but counter is 100 , although both T1 and T2 have completed execution.
Regarding the last question:
we have hb (w, r), but this does not mean that c will contain the value 3 after assignment. How to ensure c is assigned 3?
public volatile int v; public int c; Thread A v = 3;
Since v is volatile, how it is executed before ordering
Writes to an unstable field (§8.3.1.4) - before each subsequent reading of this field.
Therefore, we can safely assume that when Thread B tries to read the variable v , it will always read the updated value, and c will be assigned 3 in the above code.