First off the code, from JCIP listing http://jcip.net/listings/StuffIntoPublic.java and http://jcip.net/listings/Holder.java
public class SafePublication {
public static void main(String[] args) throws InterruptedException {
// System.out.println(Thread.currentThread().getName());
StuffIntoPublic t = new StuffIntoPublic();
t.initialize();
while (true) {
new Thread(() -> { t.holder.assertSanity(); }).start();
}
}
}
//@author Brian Goetz and Tim Peierls
class StuffIntoPublic {
public Holder holder;
public void initialize() {
// System.out.println(Thread.currentThread().getName());
holder = new Holder(42);
}
}
//@author Brian Goetz and Tim Peierls
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.");
}
}
}
I am saying that the AssertionError will never be thrown in this case because of the Thread.start() happens before guarantee. Both of the System.out.printlns that are commented prints main, meaning that the main thread is which spawns all the later threads by making and calling start on the threads in the while(true) loop.
And since that is the thread that created and initialized Holder, all subsequent threads are safe to be a perfectly visible holder due to the happens-before guarantee. Am I right?
I even tried running this code for a really long time and no assertion errors.
However, if the main looked like below, then I believe it will be possible for an AssertionError
public static void main(String[] args) throws InterruptedException {
System.out.println(Thread.currentThread().getName());
StuffIntoPublic t = new StuffIntoPublic();
new Thread(() -> t.initialize() ).start();
while (true) {
new Thread(() -> { t.holder.assertSanity(); }).start();
}
}