使用单一检查习语进行延迟初始化

时间:2012-12-20 21:43:32

标签: java volatile lazy-initialization effective-java

在“Effective Java,Second Edition”的第71项中,为了延迟实例化实例字段,引入了双重检查惯用语和单一检查用语。

仔细检查成语

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

单一检查成语

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

在Joshua所述的复核习语中,结果变量用于确保仅读取一次易失性字段,从而提高性能。我理解这一点,但是我不明白为什么我们在单一检查习语中需要它,因为我们只读过 field

2 个答案:

答案 0 :(得分:5)

在单一检查成语中,如果没有结果变量,你仍然会读两遍;一次用于空检查,一次用于返回值。

答案 1 :(得分:1)

我更喜欢以下懒惰评估的实现:

@ThreadSafe
class MyClass {
    private static class MyClassHelper {
       public static final MyClass helper = new MyClass();
    }

    public static MyClass getInstance() {
        return MyClassHelper.helper;
    }
}