0

我无法理解A fix that doesn't work下面的代码片段。(我确实阅读了同一页上的解释)。

如果我们有 2 个同步块,这个 DCL 版本是如何损坏的?或者它在 Java5 之后不适用?

// (Still) Broken multithreaded version
// "Double-Checked Locking" idiom
class Foo { 
  private Helper helper = null;
  public Helper getHelper() {
    if (helper == null) {
      Helper h;
      synchronized(this) {
        h = helper;
        if (h == null) 
            synchronized (this) {
              h = new Helper();
            } // release inner synchronization lock
        helper = h;
        } 
      }    
    return helper;
    }
  // other functions and members...
  }
4

1 回答 1

3

不能保证看到helper为非 null 的线程将能够看到所有由new Helper();. 所以你可以访问一个损坏的单例版本。您需要在线程中看到一些东西,helpernull保证它在完成h = new Helper();看到它。观察非易失性变量的变化不会建立这样的关系,这就是线程所做的一切。

稍微简化一下,Java 的内存可见性模型的工作方式是两个线程各自做一些事情,在两个线程完成的两个操作之间建立“发生在之前”/“发生在之后”的关系。这可以包括同步块内的操作或对 volatile 变量的访问。

但是使用上面的代码,线程可以观察到helper不是null,然后继续访问由new Helper(). 它不必访问volatile变量,也不必进入同步块。因此,没有什么可以建立所需的“发生在”关系以确保它看到由new Helper().

于 2015-11-20T08:05:02.247 回答