非易失性领域的发布和阅读 [英] Publishing and reading of non-volatile field

查看:36
本文介绍了非易失性领域的发布和阅读的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

public class Factory {
    private Singleton instance;
    public Singleton getInstance() {
        Singleton res = instance;
        if (res == null) {
            synchronized (this) {
                res = instance;
                if (res == null) {
                    res = new Singleton();
                    instance = res;
                }
            }
        }
        return res;
    }
}

它几乎是线程安全的Singleton 的正确实现.我看到的唯一问题是:

It is almost correct implementation of thread-safe Singleton. The only problem I see is:

正在初始化 instance 字段的 thread #1 可以在它完全初始化之前发布.现在,第二个线程可以在不一致的状态下读取 instance.

The thread #1 that is initializing the instance field can published before it will be initialized completely. Now, the second thread can read instance in a inconsistent state.

但是,在我看来,这是唯一的问题.只有这里有问题吗?(并且我们可以使 instance 变得不稳定).

But, for my eye it is only problem here. Is it only problem here? (And we can make instance volatile).

推荐答案

你的例子由 Shipilev 在 Java 中的安全发布和安全初始化.我强烈建议阅读整篇文章,但总结起来看那里的 UnsafeLocalDCLFactory 部分:

You example is explained by Shipilev in Safe Publication and Safe Initialization in Java. I highly recommend to read the whole article, but to sum it up look at UnsafeLocalDCLFactory section there:

public class UnsafeLocalDCLFactory implements Factory {
  private Singleton instance; // deliberately non-volatile

  @Override
  public Singleton getInstance() {
    Singleton res = instance;
    if (res == null) {
      synchronized (this) {
        res = instance;
        if (res == null) {
           res = new Singleton();
           instance = res;
        }
      }
    }
    return res;
  }
}

以上存在以下问题:

这里引入局部变量是一个正确性修复,但只是部分:在发布 Singleton 实例和读取其任何字段之间仍然没有发生之前.我们只是保护自己不返回null"而不是 Singleton 实例.同样的技巧也可以看作是对 SafeDCLFactory 的性能优化,即只做一次 volatile 读取,产生:

The introduction of local variable here is a correctness fix, but only partial: there still no happens-before between publishing the Singleton instance, and reading of any of its fields. We are only protecting ourselves from returning "null" instead of Singleton instance. The same trick can also be regarded as a performance optimization for SafeDCLFactory, i.e. doing only a single volatile read, yielding:

Shipilev 建议修复如下,将 instance 标记为 volatile:

Shipilev suggests to fix as follows, by marking instance volatile:

public class SafeLocalDCLFactory implements Factory {
  private volatile Singleton instance;

  @Override
  public Singleton getInstance() {
    Singleton res = instance;
    if (res == null) {
      synchronized (this) {
        res = instance;
        if (res == null) {
          res = new Singleton();
          instance = res;
        }
      }
    }
    return res;
  }
}

这个例子没有其他问题.

There are no other problems with this example.

这篇关于非易失性领域的发布和阅读的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆