【问题标题】:Why DCL without volatile is valid for primitives?为什么没有 volatile 的 DCL 对原语有效?
【发布时间】:2019-09-19 13:27:57
【问题描述】:

免责声明:我不在实际生产代码中使用 DCL - 我只对学术感兴趣。

我读过以下著名文章:The "Double-Checked Locking is Broken" Declaration

问题声明(我的愿景):

// Correct multithreaded version
class Foo { 
  private Helper helper = null;
  public synchronized Helper getHelper() {
    if (helper == null) 
        helper = new Helper();
    return helper;
    }
  // other functions and members...
  }

假设 thread_1 执行了行 helper = new Helper(); 另一个线程(thread_2)might 看到 helper 链接不为空但尚未初始化。这是因为构造函数调用可能会使用helper 链接分配重新排序 来自thread_2veiw。

但在这篇文章中提到,这种方法适用于 32 位原语。

虽然双重检查锁定习语不能用于 对对象的引用,它可以用于 32 位原始值(例如, 整数或浮点数)。请注意,它不适用于 long 或 double, 因为 64 位原语的非同步读/写不是 保证是原子的。

// Correct Double-Checked Locking for 32-bit primitives
class Foo { 
  private int cachedHashCode = 0;
  public int hashCode() {
    int h = cachedHashCode;
    if (h == 0) 
    synchronized(this) {
      if (cachedHashCode != 0) return cachedHashCode;
      h = computeHashCode();
      cachedHashCode = h;
      }
    return h;
    }
  // other functions and members...
  }

请解释一下为什么它有效?我知道 32 位写入是原子的。

这里的局部变量是什么原因?

【问题讨论】:

    标签: java multithreading concurrency volatile java-memory-model


    【解决方案1】:

    “DCL 已损坏”比喻的本质是,使用 DCL 初始化单例对象,线程可以在看到对象处于完全初始化状态之前看到对该对象的引用。 DCL 充分同步了引用单例的有效最终全局变量,但无法同步全局引用的单例对象。

    在您的示例中,只有全局变量。没有“它所指的对象”。

    【讨论】:

      猜你喜欢
      • 2016-11-05
      • 1970-01-01
      • 2018-10-06
      • 2012-10-03
      • 2012-10-11
      • 1970-01-01
      • 1970-01-01
      • 2011-10-03
      • 1970-01-01
      相关资源
      最近更新 更多