Пожалуйста, объясните безопасность инициализации, как указано в модели памяти Java.

  1. Может ли кто-нибудь объяснить безопасность инициализации в соответствии с требованиями модели памяти Java?
  2. Как поля final помогают в достижении безопасности инициализации?
  3. Какую роль конструктор играет в обеспечении безопасности инициализации?

person Inquisitive    schedule 03.07.2012    source источник


Ответы (2)


Безопасность инициализации обеспечивает видимость объекта внешним потоком в его полностью сконструированном (инициализированном) состоянии. Обязательным условием является то, что объект не должен быть опубликован преждевременно, т.е. в его конструкторе. Как только это будет обеспечено, JMM требует определенного поведения для полей, объявленных как final. Во-первых, все final поля объекта гарантированно будут видны внешнему потоку в полностью инициализированном состоянии. Это не так тривиально, как кажется.

Рассмотрим класс:

class A {
   List list;
   A() {  
      list = Arrays.asList(some init expressions that adds 10 elements to list);
    }

}

Поток, который обращается к экземпляру list из A's, по умолчанию не гарантированно увидит 10 элементов в этом списке. Фактически, этот поток может даже видеть list как null. Однако, если list объявлен final, тогда, как требуется JMM, list всегда должен быть инициализирован с 10 элементами в нем.

Во-вторых, эта гарантия инициализации не ограничивается самим полем final, а рекурсивно распространяется на все объекты, на которые оно ссылается. Например, если list в приведенном выше примере является списком самих списков, то внешний поток гарантированно увидит внутренние списки как полностью инициализированные.

Обратите внимание, что нигде мы не используем synchronized для достижения этой безопасности в видимости памяти (отношения «происходит до»).

person Bhaskar    schedule 03.07.2012
comment
+1 за упоминание о том, что безопасность инициализации гарантирует безопасность не только для конечных полей, но и для объектов, на которые ссылаются конечные поля. - person Inquisitive; 03.07.2012

1. Безопасность инициализации позволяет правильно сконструировать неизменяемые объекты для безопасного совместного использования между потоками без использования синхронизации, даже если они опубликованы с использованием гонки данных.

2. Объекты, имеющие конечное поле, безопасность инициализации предотвращают переупорядочивание любой части конструкции с начальной загрузкой ссылки на этот объект.

person Kumar Vivek Mitra    schedule 03.07.2012
comment
независимо от того, опубликованы ли они с использованием гонки данных. В этой строке вообще нет никакого смысла. Объекты не публикуются с использованием гонок данных :-). - person Inquisitive; 03.07.2012
comment
Я не уверен, что не допустит переупорядочения какой-либо части конструкции. Гарантии для полей final действуют только для инициализации этих полей final, но не для других частей конструкции. - person axtavt; 03.07.2012
comment
Фактическое переупорядочение @axtavt предотвращается за счет того, что поле volatile не является окончательным. Так что пункт 2, на мой взгляд, неверен. - person Inquisitive; 03.07.2012