双重检查单例学习
程序员文章站
2022-04-15 23:09:33
单例模式是java开发模式最常用的一种。 今天深入学习双重检查单例。先看几种典型单例代码: private Sington(){ } // 方案1 // 最简单单例,final 保证只能new一下 // 不能接受启动就创建对象。万一不用不就浪费了? private static final Sington instans0=new Sington(); public static Sington instance0(){ retu...
单例模式是java开发模式最常用的一种。 今天深入学习双重检查单例。
先看几种典型单例代码:
private Sington(){
}
// 方案1
// 最简单单例,final 保证只能new一下
// 不能接受启动就创建对象。万一不用不就浪费了?
private static final Sington instans0=new Sington();
public static Sington instance0(){
return instans0;
}
// 方案2
// 方法加锁,进阶懒加载
// 锁住了整个方法, 每次调用都lock一下也不能接受
private static Sington instans1=null;
public synchronized static Sington instance(){
if(instans1==null){
instans1=new Sington();
}
return instans1;
}
// 方案2 类似
private static Sington instans2=null;
public static Sington instance2(){
synchronized(Sington.class){
if(instans2==null){
instans2=new Sington();
}
}
return instans2;
}
// 方案3:双重检查单例
// 懒加载
// 上来无脑加锁不能接受,增加null判断。
// 问题又来了:为啥要用volatile???
private static volatile Sington instans3=null;
public static Sington instance3(){
if(instans3==null){
synchronized(Sington.class){
if(instans3==null){
instans3=new Sington();
}
}
}
return instans3;
}
重点来了:volatile 存在的意义是什么?
这里涉及了好几个知识点 ,指令重排,内存屏障,类实例化过程。
volatile 有什么特性?
- 线程可见
- 禁止指令重排序
什么是指令重排?
这里不深入解释,简单来说,在多线程环境下,cpu指令为了提升性能,对于没有绝对先后顺序的指令存在乱序执行的可能性。
了解类的实例化
类实例化主要3个步骤实例化->初始化->返回。 在实例化过程中存在初始化还没执行,已经返回了。
线程2拿到未初始化的实例对象, 后续时候就会报错。
本文地址:https://blog.csdn.net/tkascor/article/details/107489655