【问题标题】:Atomicity of operation on volatilevolatile 操作的原子性
【发布时间】:2017-05-08 13:26:04
【问题描述】:

我的问题与this post有关。

public class SafeDCLFactory {
  private volatile Singleton instance;

  public Singleton get() {
    if (instance == null) {  // check 1
      synchronized(this) {
        if (instance == null) { // check 2
          instance = new Singleton(); // store
        }
      }
    }
    return instance;
  }
}

这是一场数据竞赛。线程 1 可以读取 instance(检查 1),而线程 2 写入(存储)。

为什么安全? store 操作在这里是原子的吗?如果没有怎么办?

【问题讨论】:

标签: java multithreading java-memory-model


【解决方案1】:

从技术上讲,外部 if 语句不是必需的。这是一个优化。如果我们删除它,就会更容易看到发生了什么。

public Singleton get() {
    synchronized(this) {
        if (instance == null) {
            instance = new Singleton();
        }
    }
    return instance;
}

在这个例子中,我们知道 - 感谢同步 - 对于这个工厂实例,任何时候只有一个线程可以在 synchronized 块中。然后check-then-act 是安全的。 instance 不能初始化两次。

但是,此实现存在问题。每次我们尝试获取实例时,我们都需要同步。这实际上并没有最大限度地利用货币。它可能会不必要地阻塞其他线程。

这就是我们添加额外检查的原因。可能有多个线程尝试同时进行初始化,但在这段短暂的时间之后,我们将不再需要再次进行同步。

public Singleton get() {
    if (instance == null) {

        //instance may actually have been created now by another thread

        synchronized(this) {
            if (instance == null) {
                instance = new Singleton();
            }
        }
    }
    return instance;
}

这里的store操作是原子的吗?

是的。 Assignment of references in Java is atomic.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-25
    • 1970-01-01
    • 2015-10-15
    • 2013-05-07
    • 1970-01-01
    • 2015-08-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多