Я пытаюсь решить простую проблему и попадаю в отверстие для кроликов Java-памяти.
Что является самым простым и/или наиболее эффективным (звонок суждения здесь), но гонка бесплатно (точно определены в соответствии с ЯВМ) способом написания класса Java, содержащий <сильного > неконечного ссылки на поле который инициализируется ненулевым значением в конструкторе и впоследствии никогда не изменяется, так что никакой последующий доступ этого поля ни к какому другому потоку не может видеть ненулевое значение?
Пример неудачного запуска:
public class Holder {
private Object value;
public Holder(Object value) {
if (value == null)
throw NullPointerException();
this.value = value;
}
public Object getValue() { // this could return null!
return this.value;
}
}
И в соответствии с этот пост, обозначение поля volatile
даже не работает!
public class Holder {
private volatile Object value;
public Holder(Object value) {
if (value == null)
throw NullPointerException();
this.value = value;
}
public Object getValue() { // this STILL could return null!!
return this.value;
}
}
Это лучшее, что мы можем сделать?
public class Holder {
private Object value;
public Holder(Object value) {
if (value == null)
throw NullPointerException();
synchronized (this) {
this.value = value;
}
}
public synchronized Object getValue() {
return this.value;
}
}
Как насчет этого?
public class Holder {
private Object value;
public Holder(Object value) {
if (value == null)
throw NullPointerException();
this.value = value;
synchronized (this) { }
}
public synchronized Object getValue() {
return this.value;
}
}
Боковое примечание: связанный вопрос спрашивает, как это сделать без использования volatile
или синхронизации, что, конечно, невозможно.