см. устаревшее значение = 0. И мне кажется, что невозможно воспроизвести это поведение.

аю книгу Брайана Гетца «Параллелизм Java на практике». Пункты 3.5 и 3.5.1 содержат утверждения, которые я не могу понять.

Рассмотрим следующий код:

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);  
  }
}

Автор утверждает, что:

В Java конструктор объекта сначала записывает значения по умолчанию во все поля перед запуском конструктора подкласса.Поэтому можно видеть значение поля по умолчанию как устаревшее значение.Поток может увидеть устаревшее значение при первом чтении поля, а затем в следующий раз более актуальное значение, поэтому assertN может выдать AssertionError.

Итак, согласно тексту, при некоторой неудачной синхронизации возможно, что значение = 0; и в следующий момент значение = 42.

Я согласен с пунктом 1, что конструктор объекта сначала заполняет поля значениями по умолчанию. Но я не понимаю пунктов 2 и 3.

Давайте обновим код авторов и рассмотрим следующий пример:

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");
  }
}

Я добавил Thread.sleep (3000), чтобы заставить поток ждать, пока объект не будет полностью построен.

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();
  }
}

В примере:

первая нить в объекте держателявторой поток вызывает assertValue

Основной поток запускает два потока:

новый поток (новая инициализация ()). start (); Требуется 3 секунды, чтобы полностью построить объект Holder.новая тема (новая проверка ()). начало (); так как объект Holder все еще не сконструированный код броситИсключение нулевого указателя

Поэтому невозможно эмулировать ситуацию, когда поле имеет значение по умолчанию.

Мои вопросы:

Автор был неправ об этой проблеме параллелизма?Или это невозможно эмулировать поведение для значений полей по умолчанию?

Ответы на вопрос(3)

Ваш ответ на вопрос