package com.zzfl.pm1; /** * ZZFL 2019/8/11 */ public class SingleTon { private SingleTon(){ //禁止反射破解 synchronized (SingleTon.class) { if (instance != null) { throw new RuntimeException("不能使用反射进行创建对象"); } } } /* volatile:不稳定的,易挥发的。 */ private static volatile SingleTon instance; public static SingleTon getInstance(){ if (instance == null) {//双重检测,提高效率 synchronized (SingleTon.class) {//加锁,保证共享资源的原子性 if (instance == null) { instance=new SingleTon(); } } } return instance; } } class Demo{ public static void main(String[] args){ Runnable runnable=new Runnable() { @Override public void run() { SingleTon singleTon=SingleTon.getInstance(); System.out.println(singleTon.hashCode()); } }; new Thread(runnable, "窗口1").start(); new Thread(runnable, "窗口2").start(); new Thread(runnable, "窗口3").start(); new Thread(runnable, "窗口4").start(); } }
对象在虚拟机中实例化的时候对多线程可能产生的影响:
正常情况下,在创建一个实例化对象的时候,①首先是在堆中开辟空间,②然后调用构造方法对属性进行初始化,③最后把实例化对象地址赋值给栈空间中的变量。但是实际上在JVM运行的过程中有可能会对代码进行优化,优化成①③②。假如有一个线程A在进行实例化一个对象的过程中,被优化成①③②,但是当执行到步骤三的时候A线程的CPU此时到期,那么线程B在对该获取对象的时候,此时该对象时候通过判断发现该对象已经被实例化过了因为栈空间当中已经存有实例化对象的地址,但是由于A线程并没有对实例化对象属性进行初始化,因此在B线程获取该实例化对象的属性的时候有可能造成空指针异常。因此,如果对共享资源属性加上volatile修饰词进行修饰,那么就会告诉虚拟机不要对该实例化对象进行优化,而这个优化的过程就叫做指令重排序。
volatile作用:
1)保证线程可见性
2)禁止指令重排序