阅读了几篇关于DCL的文章。我觉得我不应该在没有volatile的情况下使用这个概念。如果我不引导这种技术,我的代码将不会根据一个不同的原因进行线程保存并且非常非常糟糕。
最近我重读了基础知识Happens Before,我有一点另一种观点
让研究单例代码列表:
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
point 2
可能会返回null;
答案 0 :(得分:0)
示例中的问题不是,可能会创建两个实例。这是真的,只会创建一个实例。真正的问题是,在多线程访问此方法时,其他线程可以开始使用部分构造的instance
(1) (2)版本。
因此,instance
变量应明确定义为volatile
(在您的代码块中遗漏),否则您应该关注"新鲜度"这个变量的值。
因为如果字段已经初始化,则没有锁定,它是 关键是该领域被宣布为挥发性的(项目66)[J. Bloch," Effective Java",Item 71]
所以:
private static volatile Something instance;
(顺便说一句,明确指定null
值是多余的。)
为什么没有" volatile"很好解释here:
最明显的原因是它的写作没有 初始化Helper对象并写入helper字段即可 完成或感觉无序