Consider the snippet from Java Concurrency in Practice-
// Unsafe publication
public Holder holder;
public void initialize(){
holder = new holder(42);
}
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.");
}
}
One of the solutions suggested by the author of the book is -
public static Holder holder = new Holder(42);
And if the only requirement was to prevent the AssertionError
, then this would also work fine-
private final int n;
My question is a follow-up to the comment on this stackoverflow thread by John Vint-
Actually, declaring the member field volatile still doesnt guarantee publication prior to holder being visible. You can look at ConcurrentHashMap's private method readUnderLock in which that takes this nuance into account. Though declaring holder as volatile does.
To put it in simple words, he is suggesting hereby 2 things-
public volatile Holder holder;
public void initialize(){
holder = new holder(42);
}
Is the above solution going to work perfectly? If a reference to an object is declared as volatile, does it ensures safe object publication? Arrays are objects too. Declaring an array reference doesn't makes its elements thread safe.
And Why this will not work as suggested by author-
public class Holder {
private volatile int n;
declaring the member field volatile still doesnt guarantee publication prior to holder being visible
Even though as the member field has been declared as volatile, its gauranteed that the condition n != n
will be always false, and hence no AssertionError
. Please suggest.