您的位置:首页 > 编程语言 > Java开发

单例模式中最常见的双if语句错误

2018-04-04 15:18 232 查看
单例模式中,最常见的代码错误,代码如下:
public class Singleton {

//持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载
private static Singleton instance=null;

//私有构造方法
private Singleton(){

}

//静态工程方法,创建实例
public static Singleton getInstance(){
if (instance == null) {
synchronized (instance) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}

看起来好像没什么问题.但是由于JVM内部的优化机制.
instance = new Singleton()在JVM中这句话中大概做了以下3件事情
1.给 instance 分配内存
2.调用 Singleton 的构造函数来初始化成员变量
3.将instance对象指向分配的内存空间(执行完这步 instance 就为非 null 了)

在多线程中,JVM的计时编程器中存在指令重排序的优化.也就是说上面的第二步和第三步的顺序是不能保证的,最终的执行顺序可能是 1-2-3 也可能是1-3-2.如果是后者,当A线程的第3步骤执行完毕,第2步骤还未执行之前.B线程抢到锁时,此时的instance已经是非null了(但是没有初始化),此时B线程打算使用Singleton实例,却发现它没有被初始化,于是错误发生了。
这时候我们可以把代码改成

public class Singleton {

//持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载
private volatile static Singleton instance=null;

//私有构造方法
private Singleton(){

}

//静态工程方法,创建实例
public static Singleton getInstance(){
if (instance == null) {
synchronized (instance) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
细心的同学会发现,此时我把 instance 变量声明成 volatile .
当instance声明为instance时,他能保证JVM中3个步骤依次进行..
如果,你觉得这篇文章对你有帮助.你可以点赞鼓励一下我噢.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java设计模式