首先 ConcurrentModificationException 是在遍历时发生的.
背景知识:
- 遍历分为
fori,foreach,iterator三种方式 -
fori在删除 / 新增元素时, 多线程下可能导致数组索引越界 / 数据混乱 (因为索引对不上) -
foreach,iterator可能导致ConcurrentModificationException - 集合使用
foreach底层本质上是调用的iterator
ConcurrentModificationException 异常原因有两种情况 (本质上的逻辑都是checkForComodification(), 即比较 list.modCount == itr.expectedModCount):
- 单线程下
foreach/iterator遍历时, 使用list.remove()会抛出异常 (modCount被修改, 但是expectedModCount还是旧值, 抛出异常) -
- 多线程下
foreach/iterator遍历时, 使用iterator.remove()可能会抛出异常 (虽然iterator.remove()方法会重新把expectedModCount的值复制给modCount. 但是存在线程安全问题. 在iterator.next()方法时, 还会校验modCount == expectedModCount, 不等则抛出异常)