Ниже приведен пример книги "Java Concurrency на практике" Брайана Гетца, глава 3, раздел 3.5.1. Это пример ненадлежащей публикации объектов
class someClass {
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");
}
}
В нем говорится, что держатель мог появиться в другом потоке в несогласованном состоянии, а другой поток мог бы наблюдать частично построенный объект. Как это может произойти? Не могли бы вы дать сценарий, используя приведенный выше пример?
Далее следует, что бывают случаи, когда поток может видеть устаревшее значение при первом чтении поля, а затем в более позднем значении в следующий раз, поэтому assertSanity может вызывать Assertion Error. Как может быть вызвано assertionError?
Из дальнейшего чтения один из способов устранить эту проблему состоит в том, чтобы сделать Холдер неизменным, сделав переменную 'n' final. Предположим теперь, что Холдер не является непоколебимым, но эффективно неизменным. Чтобы безопасно публиковать этот объект, нам нужно сделать статическую инициализацию владельца и объявить ее изменчивой (как статической, так и изменчивой или просто изменчивой)? Что-то вроде
public class someClass {
public static volatile Holder holder = new Holder(42);
}
Спасибо за вашу помощь заранее.