为什么单例模式懒汉式doublecheck要使用volatile关键字修饰
public class SingletonTest06 {
public static void main(String[] args) {
//测试
Singleton instance = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance == instance2); // true
System.out.println(" instance.hashCode=" + instance.hashCode());
System.out.println(" instance2.hashCode=" + instance2.hashCode());
}
//懒汉式(线程安全,同步方法)
static class Singleton {
private static volatile Singleton instance;
private Singleton() {
}
//提供一个静态的公有方法,加入双重检查代码,解决线程安全问题,同时解决懒加载问题/同时保证了效率,推荐使用
public static synchronized Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
}
instance = new Singleton();
这一步实际的操作可被分为了三步:
1分配内存空间属性赋默认初始值(0、false等0值);
2属性赋初值或构造函数值(赋真实值);
3将instance位置指向此处内存空间;
但是这三步有可能被cpu进行指重排序,导致线程1在创建instance时先1后3(则此时singleton已有null变为有真正的指向),若这时线程2得到cup进来了发现singleton已不为null,便将其拿入工作副本实用,则会出现问题;这种概率极小但一旦发生在某些业务中可能就是致命的,所以此处需要禁止指令重排序,而volatile便有这个功能(可见性,禁止指令重排序)