多线程并发出现异常的情况
单例模式
public class DoubleCheckSingleton {
/**
* 使用volatile,在多线程场景下,确保在判断null时,对所有线程可见
*/
private static volatile DoubleCheckSingleton uniqInstance;
/**
* 构造器私有,防止外部实例化该类
*/
private DoubleCheckSingleton() {}
/**
* 静态方法实例化,由于在类内部,可以调用构造器
*/
public static DoubleCheckSingleton getInstance(){
if (null == uniqInstance) { // 此处判断需要可见性volatile
synchronized (DoubleCheckSingleton.class) {
if (null == uniqInstance) {
//延迟初始化
uniqInstance = new DoubleCheckSingleton();
}
}
}
return uniqInstance;
}
}
可见性
- 引发原因
CPU高速缓存 由于各个线程会在执行是从 主存 加载到CPU高速缓存中执行,节省读取内存时间(CPU速度>> 主存速度)
线程A对共享变量V做了修改,其它线程B看到V的值还是之前的old失效数据
- 后果(以单例模式举例)
失效数据
线程A已经创建了instance,但是线程B读取的instance还是null,会导致创建了两个instance,A和B拿到的实例不一样!!
失效值可能导致错误的结果或者导致活跃性问题。
- fix方案
volatile
加锁(syn、lock)
有序性
- 引发原因
编译优化之指令重排序
CPU执行指令时会有一些指令重排序以期最大效率
- 后果(以单例模式举例)
单例模式赋值和实例化的重排序导致的异常
- fix方案
volatile
加锁
通过Happens-before规则实现
内置锁的释放锁操作发生在该锁随后的加锁操作之前
一个volatile变量的写操作发生在这个volatile变量随后的读操作之前