public class SingleDoubleLock {
/*
假设没有关键字volatile的情况下,两个线程A、B,都是第一次调用该单例方法,
线程A先执行instance = new Instance(),该构造方法是一个非原子操作,
编译后生成多条字节码指令,由于JAVA的指令重排序,可能会先执行instance的赋值操作, 该操作实际只是在内存中开辟一片存储对象的区域后直接返回内存的引用,之后instance便不为空了,但是实际的初始化操作却还没有执行,如果就在此时线程B进入,
就会获得一个不为空的但是不完整(没有完成初始化)的Instance对象,
所以需要加入volatile关键字,禁止指令重排序优化,从而安全的实现单例
*/
private static volatile SingleDoubleLock single= null;
private SingleDoubleLock(){}
/*
* 1 第一次校验:因为该类是单例的只创建一次,大部分时间single都不为空,所以不会进行第一次检验的代码块内部,从而提高效率
* 2 第二次校验:如果single为空,线程t1,t2进入第一次检验的代码块,
* t1执行synchronized代码块-》new完对象且没有return-》如果不进行第二次校验,
* t2对象进入synchronized代码块又new了一次,导致创建了多个实例
*/
public static SingleDoubleLock getInstance(){
//
//不加volatile,线程B走到这里
//
if(single == null){
synchronized (SingleDoubleLock.class) {
if(single == null){
single = new SingleDoubleLock();//不加volatile,线程A走到这里,这里是非原子操作
}
}
}
return single;
}
}
单例双重校验锁
最新推荐文章于 2024-05-16 20:06:13 发布