//双重校验锁实现对象单例(线程安全)
public class Singleton {
private volatile static Singleton uniqueInstance;
private Singleton(){
}
public static Singleton getUniqueInstance(){
//先判断对象是否已经实例过,没有实例化过才进入加锁代码
if (uniqueInstance == null){
//类对象加锁
synchronized (Singleton.class){
if (uniqueInstance == null){
uniqueInstance = new Singleton();//这段代码分为三步执行
//1.为uniqueInstance分配内存空间
//2.初始化uniqueInstance
//3.将uniqueInstance指向分配的内存空间
}
}
}
return uniqueInstance;
}
}
JVM
具有指令重排的特性,执行顺序可能变为1-3-2.指令重排在单线程环境下不会出现问题,但是在多线程环境下会导致一个线程获得还没有初始化的实例。例如,线程T1执行了1和3,2还没有执行,线程T2调用getUniqueInstance()
后发现uniqueInstance
不为空,因此返回uniqueInstance
,但此时uniqueInstance
还没有被初始化。
volatile
可以禁止JVM
的指令重排,保证在多线程环境下也能正常运行。