面试常考设计模式
单例模式 4
懒汉(线程不安全)
1 | public class Singleton { |
如果有多个线程能进入 if(uniqueInstance == null) 并且此时 uniqueInstance 为空,就会实例化多个Single
双重校验
1 | public class Singleton { |
之所以要进行两次 if 判断,是因为如果两个线程同时执行 if 语句,两个线程都会进入 sychronized 语句块,等到第一个线程完成实例化之后第二个线程也会进入。为了避免第二次实例化,第二个线程如果判断得到uniqueInstance不为空,就不会进行实例化了,保证了只有一个实例
volatile 可以禁止指令重排,因为 uniqueInstance = new Singleton(); 这段代码实际是分3步执行的:
- 为 uniqueInstance 分配内存空间
- 初始化uniqueInstance
- 将uniqueInstance指向被分配的内存地址
由于JVM的执行重排特性,这段代码可能是按照1-3-2的顺序执行的,如果T1线程执行了1和3,T2线程调用getInstance发现不为空,就返回了 uniqueInstance ,但此时uniqueInstance还未被初始化