【问题标题】:Single- and double-check lazy initialization单一和双重检查延迟初始化
【发布时间】:2015-01-20 15:07:59
【问题描述】:

我无法理解“Effective Java”中第 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;
}

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

【问题讨论】:

  • 上例中的第 6 行应该是 result = field;不是 ==,不是吗?

标签: java multithreading thread-safety lazy-initialization


【解决方案1】:

双重检查锁定的要点是它确保computeFieldValue 只被调用一次,并且该字段只被写入一次。

在某些情况下,多次调用此方法是可以接受的,这使得双重检查锁定过度。以下是需要满足的一些条件:

  • computeFieldValue 应该是一个纯函数,总是返回相同的值;
  • 它被多次调用的风险程度是可以接受的(发生这种情况的几率乘以它对性能的影响)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-17
    相关资源
    最近更新 更多