List并发修改异常探究

ConcurrentModificationException

Posted by Peakiz on March 16, 2022 Views:

0 什么情况下会出现ConcurrentModificationException异常?

ConcurrentModificationException继承自RuntimeException;

在使用迭代器或者增强for循环(底层也是利用的迭代器)遍历的时候,使用集合的增删改方法对集合进行更新操作的时候会出现这个异常;

1
2
3
4
5
6
7
8
9
10
        List<Integer> list = new LinkedList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        for (int x : list) {
            if (x == 2) {
                list.remove(x);
            }
        }

异常代码:

1
2
3
4
Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:966)
	at java.util.LinkedList$ListItr.next(LinkedList.java:888)
	at Main.main(Main.java:18)

1 ConcurrentModificationException出现原因分析

迭代器的next方法:

每次执行next()的时候都会先进行一次校验,校验的是List的修改次数,迭代器对象有一个变量记录了list的期望修改次数(只有通过迭代器修改才会变更这个数值),List本身也有一个记录修改次数的变量,迭代器在迭代的时候,会先判断迭代器期望的修改次数和list本身的修改次数是否一致,如果不一致就报错;

2 如何避免ConcurrentModificationException异常?

  • 普通for循环
  • 直接使用迭代器
  • 使用stream()流处理过滤
  • Collection.removeIf()
  • 使用CopyOnWriteArrayList并发安全的数据结构