一.场景
场景1:
并发流parallelStream中使用ArrayList添加数据
场景2:
并发流parallelStream中使用定长ArrayList添加数据
场景3:
遍历取出Arraylist的new User()对象,判断是否对象会为null
二.现象
现象1:
报错,超出数组上限:
现象2:
不报错,但ArrayList中数量错误:
现象3:
报错,会产生对象为null的数据
三.结论
1,2 现象原因是因为并发流中使用的是非线程安全的ArrayList,应该使用线程安全的类,例如Vector或者synchronizedList
3 现象原因是因为JAVA字节码指令重排导致:由于指令重排,原先的 申请内存地址->生成对象new User()→add添加对象地址到list集合,变更为 申请内存地址->add添加对象地址到list集合→对应地址内存存放new User()对象。
在并发情况下,list获取该地址时,对象可能还没有生成完成,故而导致空指针异常
四.扩展
1.在单一线程中,如果程序指令交换执行顺序,不影响执行结果,JAVA字节码指令集会重新排序java代码,除以下情况不会重排:
2.字节码源码分析,引用多线程情况下实例化对象发生指令重排而造成空指针问题_mengXi_0718的博客-CSDN博客
3.双重检测为何也会生成多例的原因也是如此,volatile 关键词不可少,一般采用静态内部类来生成单例