懒汉式单例的double check、例一:多线程
1 class SingletonClass{ 2 private static SingletonClass instance = null; 3 4 private SingletonClass() {} 5 6 public static SingletonClass getInstance() { 7 if(instance==null) { 8 synchronized ( SingletonClass.class) { 9 if(instance==null) 10 instance = new SingletonClass();//语句1 11 } 12 } 13 return instance; 14 } 15 }
上面的代码在多线程下调用可能会报错,具体报错缘由:函数
在语句1中并非一个原子操做,在JVM中实际上是3个操做:
1.给instance分配空间、
2.调用 Singleton 的构造函数来初始化、
3.将instance对象指向分配的内存空间(instance指向分配的内存空间后就不为null了);
在JVM中的及时编译存在指令重排序的优化,也就是说不能保证1,2,3执行的顺序,最终的执行顺序多是 1-2-3 也多是 1-3-2。若是是 1-3-2,则在 3 执行完毕、2 未执行以前,被线程二抢占了,这时 instance 已是非 null 了(但却没有初始化),因此线程二会直接返回 instance,而后使用,而后瓜熟蒂落地报错。
经过添加volatile就能够解决这种报错,由于volatile能够保证一、二、3的执行顺序,没执行玩一、2就确定不会执行3,也就是没有执行完一、2instance一直为空,具体代码以下:优化
1 class SingletonClass{ 2 private volatile static SingletonClass instance = null; 3 4 private SingletonClass() {} 5 6 public static SingletonClass getInstance() { 7 if(instance==null) { 8 synchronized ( SingletonClass.class) { 9 if(instance==null) 10 instance = new SingletonClass(); 11 } 12 } 13 return instance; 14 } 15 }