在阅读了几十篇关于DCL的文章之后。我觉得如果没有volatile.If,我就不应该使用这个概念,我不会领导这种技术,我的代码不会线程保存,而且非常糟糕,因为有一百个不同的原因。
最近,我重读了以前发生的一些基本知识,我有了另一种看法。
让我们研究一下单例代码清单:
public class Singleton{
private static Something instance = null;
public static Singleton getInstance() {
if (instance == null) { // point 1
synchronized (Singleton.class) {
if (instance == null)
instance = new Something();
}
}
return instance; //point 2
}
}我们只在synchronized (Something.class) {中更改实例
因此,我们将在使用相同监视器的同步部分中看到实际值。这是我们的案子。
因此,现在我怀疑这不是有效的,而是线程安全。
我说的对吗?
只关注一个问题:
if (instance == null) {可以在实际赋值instance = new Something();之前查看非空值吗?
但我仍然绝对确信这段代码不允许创建2个单例实例
附注:
我读得更多一些,如果我们在point 1中读取非空值,return instance at point 2可以返回null;
发布于 2017-01-31 11:30:56
在您的示例中,在可能创建两个实例方面的问题不是。这是事实,只有一个实例将被创建。真正的问题是,在多个线程访问此方法时,其他线程可以开始使用部分构造的instance (1)(2)版本。
因此,instance变量应该明确地定义为volatile (这在代码块中是遗漏的),否则您应该关注这个变量的值的“新鲜度”。
因为如果字段已经初始化,则没有锁定,因此必须将字段声明为易失性(项目66),J. Bloch,“有效Java",项目71
所以:
private static volatile Something instance;(顺便说一句,显式分配null值是多余的)。
这里很好地解释了为什么没有“易失性”就不能工作
它不能工作的最明显的原因是初始化Helper对象的写操作和对助手字段的写入可以被执行或被认为是无序的。
https://stackoverflow.com/questions/41956290
复制相似问题