乐趣区

java重排序问题

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;
退出移动版