java重排序现象
我们需要了解初始化对象的过程,大致如下:
1.分配内存空间
2.初始化对象
3.将对象指向分配的内存空间
有些编译器为了提升效率,会将2 3的顺序倒置(重排序,先将对象指向分配的内存空间再初始化),因此可能发生读取到未初始化完成的对象
下面看一个例子(这里不考虑多线程问题):
在这个例子中service方法判断bo对象是否为null,若不为null,获取attr属性,表面上看没有问题,若发生重排序现象,先将对象指向分配的内存空间,此时bo不为null,但attr属性的赋值工作有可能还未完成(假设需要很长时间),则获取到的值为null,遍历集合时就会出现空指针异常
public class Demo {
private BO bo = new BO();
public void service() {
if(bo != null) {
List<String> attrs = bo.getAttr();//若发生重排序,这里取到的值会是null
attrs.stream().forEach(attr -> {
//继续其他逻辑
});
}
}
}
class BO{
public List<String> attr;
public BO() {
attr = setAttr();
}
private List<String> setAttr() {
//假设getAttrs是获取attr的方法
return getAttrs();
}
public List<String> getAttr() {
return this.attr;
}
}
如何解决?
使用volatile
关键字,禁止重排序
private volatile BO bo;
发表回复