2015-01-20 5 views
0

Я не могу понять кусок кода в пункте 71 в «Effective Java» о двойной проверки идиомы и одной проверки идиомы для ленивой инициализации полей экземпляра:Одно- и перепроверить ленивая инициализация

Двойная проверка идиома

private volatile FieldType field; 
FieldType getField() { 
    FieldType result = field; 
    if (result == null) { 
    synchronized(this) { 
     result == field; 
     if (result == null) 
     field = result = computeFieldValue(); 
    } 
    } 
    return result; 
} 

Single-проверка идиома

private volatile FieldType field; 
FieldType getField() { 
    FieldType result = field; 
    if (result == null) { 
    field = result = computeFieldValue(); 
    } 
    return result; 
} 

Мы используем блокировку в первом случае, как я понимаю, для того, чтобы compute FieldValue() выполнялся атомарно. Но почему мы опускаем это во втором случае? Потому что теперь какая-то чужой поток может испортить некоторую ценность, которая принимает участие в вычислении. Что я пропустил?

+0

Строка 6 в приведенном выше примере должна быть результатом = поле; не ==, не так ли? – tamberg

ответ

4

Точка блокировки с двойной проверкой заключается в том, что он обеспечивает, чтобы computeFieldValue вызывается только один раз, а поле записано только один раз.

Бывают случаи, когда приемлемо вызывать этот метод более одного раза, делая двойную проверку блокировки переполнения. Вот некоторые из условий для удовлетворения:

  • computeFieldValue должен быть чистой функцией, всегда возвращая одно значение;
  • допустима степень риска того, что он называется более чем один раз (вероятность того, что это произойдет, умноженное на его влияние на производительность).
+0

Теперь ясно, спасибо. – Dmytro