1.懒汉模式:延迟加载,只有在真正使用的时候,才开始实例化。 1)线程安全问题 2)double check 加锁优化 3)编译器(JIT).CPU有可能对指令进行重排序,导致使用到尚未初始化的实例,可以通过添加volatile 关键字进行修饰,对于volatile修饰的字段,可以防止指令重排。
注意:volatile关键字
volatile:会禁止指令重排,什么是指令重排,重排序是指编译器和处理器为了优化程序性能而对指令序列进行排序的一种手段。比如JVM类加载的时候会将.java文件转换成.class文件,然后可以通过JIT技术(just in time即时编译技术,使用该技术能够加快java程序的执行速度),本来在JVM中类的加载是1、分配空间,2、初始化,3、引用赋值,我们可通过改变它加载的机制,将引用赋值这一步放到初始化的前面,这样就能在第二步就先将值赋予给要创建的对象,在另外一个线程进来之前就能判断到这个属性已经有值,但是这个时候如果对象还没有初始化,就会报空指针异常,volatile关键字就起到防止重排的作用。
public class LazySingletonTest { public static void main(String[] args) { new Thread( ()->{ LazySingleton instance = LazySingleton.getInstance(); System.out.println(instance); }).start(); new Thread( ()->{ LazySingleton instance = LazySingleton.getInstance(); System.out.println(instance); }).start(); } } class LazySingleton { /** * volatile 它会防止这个引用对应的空间不会重排序,防止重排序 * 字节码 * JIT, CPU JIT是just in time,即时编译技术。使用该技术,能够加速java程序的执行速度。 进行物理层面的优化 * 1.分配空间 * 2.初始化 * 3.引用赋值 */ private volatile static LazySingleton singleton; private LazySingleton(){ } public static LazySingleton getInstance(){ if(singleton == null){ synchronized (LazySingleton.class){ if (singleton == null){ singleton = new LazySingleton(); //字节码 // JIT, CPU JIT是just in time,即时编译技术。使用该技术,能够加速java程序的执行速度。 进行物理层面的优化 // 1.分配空间 // 3.引用赋值(如果t1线程引用赋值了,t2线程进来发现singleton已经有值了,如果还没而有初始化,就会报空指针异常) // 2.初始化 } } } return singleton; } }