In Java Concurrency In Practice an example* is given to demonstrate the issue of visibility, where two different threads may not see the up-to-date state of any particular mutable object because of a lack of synchronisation.
public class Holder {
private int n;
public Holder(int n) { this.n = n; }
public void assertSanity() {
if (n != n){
throw new AssertionError("This statement is false.");
}
}
In this particular example, the book states that should a Thread "A" first initialise and publish it via a Thread unsafe manner, like:
public Holder holder;
public void initialize() {
holder = new Holder(42);
}
And then a Thread "B" calls holder.assertSanity()
, that it is entirely possible that the AssertionError
will be thrown, due to an inconsistent state.
Now, I understand the basic premise of the argument, where a change made to a mutable variable may never be observed by another thread. But what I am confused here is the fact that it is comparing the same (or so I think) reference n != n
.
Doesn't this compare the value of the mutable primitive field private int n
? Regardless of the fact that n
may now be of value 42 to Thread A, and of value 0 (default) to Thread B, shouldn't a direct call to check it's value in the same thread be consistent? i.e. Calling assertSanity()
in Thread A would check if 42 != 42
, and in Thread B, 0 != 0
?
*Referenced from 3.5 Safe Publication, Listings 3.14 & 3.15 in the book.
The problem is that in the expression n != n
the variable n
will be loaded twice (assuming no optimization of the bytecode). Between these two loads, another thread could change the value.