单例模式
/**
* @description:
* 单例1 懒汉模式 double check
* @author: brave.chen
* @create: 2020-03-07 13:31
**/
public class SingleDecl {
private static SingleDecl singleDecl;
private SingleDecl() {
}
public static SingleDecl getInstance(){
if(singleDecl == null){
synchronized (SingleDecl.class){
if(singleDecl == null){
singleDecl = SingleDecl.getInstance();
}
}
}
return singleDecl;
}
}
上述代码并不是线程安全的
因为singleDecl = SingleDecl.getInstance();
这部分代码并不是原子性的,
这个操作有很多步
// 创建 Cache 对象实例,分配内存
0: new #5 // class com/query/Cache
// 复制栈顶地址,并再将其压入栈顶
3: dup
// 调用构造器方法,初始化 Cache 对象
4: invokespecial #6 // Method "<init>":()V
// 存入局部方法变量表
7: astore_1
如果遇到这种情况 那么线程2就会返回null。
如何解决
/**
* @description:
* 单例1 懒汉模式 double check
* @author: brave.chen
* @create: 2020-03-07 13:31
**/
public class SingleDecl {
private volatile static SingleDecl singleDecl;
private SingleDecl() {
}
public static SingleDecl getInstance(){
if(singleDecl == null){
synchronized (SingleDecl.class){
if(singleDecl == null){
singleDecl = SingleDecl.getInstance();
}
}
}
return singleDecl;
}
}
加了 volatile 关键字后
volatile 作用
正确的双重检查锁定模式需要需要使用 volatile。volatile主要包含两个功能。
保证可见性。使用 volatile 定义的变量,将会保证对所有线程的可见性。
禁止指令重排序优化。
由于 volatile 禁止对象创建时指令之间重排序,所以其他线程不会访问到一个未初始化的对象,从而保证安全性。
注意,volatile禁止指令重排序在 JDK 5 之后才被修复