Creación de objetos de concurrencia en Java

Estoy leyendo un libro "La concurrencia de Java en la práctica" de Brian Goetz. Los párrafos 3.5 y 3.5.1 contienen declaraciones que no puedo entender.

Considere el siguiente código:

public class Holder {
  private int value;
    public Holder(int value) { 
    this.value = value;
  }

  public void assertValue() {
    if (value != value) throw new AssertionError("Magic");
  }
}

class HolderContainer {
  // Unsafe publication
  public Holder holder;

  public void init() {
    holder = new Holder(42);  
  }
}

Author afirma que:

En Java, el constructor de objetos primero escribe valores predeterminados en todos los campos antes de ejecutar el constructor de subclase.Por lo tanto, es posible ver el valor predeterminado del campo como un valor obsoleto.Thread puede ver un valor obsoleto la primera vez que lee un campo y luego un valor más actualizado la próxima vez, por lo que afirmarN puede arrojar AssertionError.

Entonces, de acuerdo con el texto, con un tiempo desafortunado es posible que el valor = 0; y en el siguiente momento valor = 42.

Estoy de acuerdo con el punto 1 de que el constructor de objetos primero llena los campos con valores predeterminados. Pero no entiendo los puntos 2 y 3.

Actualicemos el código de los autores y consideremos el siguiente ejemplo:

public class Holder {
  int value;

  public Holder(int value) {
    //Sleep to prevent constructor to finish too early
    try {
     Thread.sleep(3000);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    this.value = value;
  }

  public void assertValue()  {
    if(value != value) System.out.println("Magic");
  }
}

He agregado Thread.sleep (3000), para forzar que el hilo espere antes de que el objeto esté completamente construido.

public class Tests {

  private HolderContainer hc = new HolderContainer();

  class Initialization implements Runnable {
    public void run() {
      hc.init();
    }
  }

  class Checking implements Runnable {
    public void run() {
      hc.holder.assertValue();
    }
  }

  public void run() {
    new Thread(new Initialization()).start();
    new Thread(new Checking()).start();
  }
}

Por ejemplo

primera rosca en su objeto titularsegundo subproceso llama afirmarValor

Main Thread ejecuta dos hilos:

new Thread (nueva inicialización ()). start (); Se necesitaron 3 segundos para construir completamente el objeto Holdernew Thread (nueva comprobación ()). start (); dado que el objeto Holder aún no está construido, el código arrojará unaExcepción de puntero nul

Por lo tanto, es imposible emular una situación cuando el campo tiene un valor predeterminado.

Mis preguntas

¿El autor estaba equivocado sobre este problema de concurrencia? O ¿Es imposible emular el comportamiento de los valores predeterminados de los campos?