单次和双次检查延迟初始化

时间:2015-01-20 15:08:00

标签: java multithreading thread-safety lazy-initialization

我无法理解“有效Java”中第71条中的一段代码。关于实例字段的延迟初始化的Double-check习语和单一检查习语:

仔细检查成语

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;
}

我们在第一种情况下使用锁定,据我所知,为了compute FieldValue()原子地执行。但为什么我们在第二种情况下省略它呢?因为现在一些外来线程可能会破坏参与计算的某些值。我错过了什么?

1 个答案:

答案 0 :(得分:4)

双重检查锁定的关键是确保computeFieldValue仅被调用一次,而字段只被调用一次。

有些情况下,可以多次调用此方法,使双重检查锁定过度杀伤。这些是满足的一些条件:

  • computeFieldValue应该是纯函数,始终返回相同的值;
  • 被调用不止一次的风险程度是可以接受的(发生这种情况的几率乘以其业绩影响)。