针对懒汉模式,为了解决线程安全引入双重校验锁机制,代码示例如下:
public class SignleObject {
private static SignleObject instance = null;
private SignleObject() { }
public static SignleObject getInstance() {
if (instance == null) {
synchronized (SignleObject.class) {
if (instance == null) {
instance = new SignleObject();
}
}
}
return instance;
}
隐患:
Java中的指令重排优化。所谓指令重排优化是指在不改变原语义的情况下,通过调整指令的执行顺序让程序运行的更快。
正常的顺序是:
1:分配对象的内存空间
2:初始化对象
3:设置instance指向刚分配的内存地址
发生指令重排:
1:分配对象的内存空间
3:设置instance指向刚分配的内存地址
2:初始化对象
指令2依赖1,但是3不依赖2
在以上的单例设计中,如果有两个线程A、B,A执行到 instance= new Singleton(),它并不是一个原子操作,jvm可以对其进行优化,如果此时指令重排,优先执行3操作,此时B线程执行instance == null不符合条件,则得到的是未进行初始化的对象。
改进后的代码:
public class SignleObject {
private static volatile SignleObject instance = null;
private SignleObject() { }
public static SignleObject getInstance() {
if (instance == null) {
synchronized (SignleObject.class) {
if (instance == null) {
instance = new SignleObject();
}
}
}
return instance;
}
volatile 可以防止指令重排,之后详细分析;