Является ли это лучшей версией двойной проверки блокировки без энергозависимости и синхронизации?
Ниже приведен фрагмент кода от эффективной блокировки Java 2-й редакции с двойной проверкой
// Двойная проверка идиомы для ленивой инициализации полей экземпляра
private volatile FieldType field;
FieldType getField() {
FieldType result = field;
if (result == null) { // First check (no locking)
synchronized(this) {
result = field;
if (result == null)// Second check (with locking)
field = result = computeFieldValue();
}
}
return result;
}
Из того, что я знаю, главная проблема с двойной проверкой блокировки - это переупорядочение внутри второй проверки блокировки, чтобы другой поток мог видеть значения поля / результата в виде набора, которые могут быть неэффективными при выполнении. Чтобы избежать этого, мы делаем ссылку на поле как изменчивую, чтобы гарантировать видимость и переупорядочение.
Но это может быть достигнуто с помощью приведенного ниже кода также
private FieldType field; // non volatile
private volatile boolean fence = false;
FieldType getField() {
if (field == null) { // First check (no locking) // no volatile read
synchronized(this) { // inside synch block no problem of visibilty will latest //value of field
if (field == null) {// Second check (with locking)
Object obj = computeFieldValue();
fence = true; // any volatile write will take. this will make sure statements are //not reorder with setting field as non null.
field = (FieldType)obj; // this will be only set after computeFieldValue has been //completed fully
}
}
}
return field;
}
Таким образом, после того, как инициализация будет выполнена, никакой поток не будет нуждаться в энергозависимом чтении или накладных расходах синхронизации. Пожалуйста, посмотрите, правильны ли мои предположения или нет?