记录一次不常见ConcurrentModificationException
前言
JDK:8
通常我们了解到这个异常出现的原因:迭代器在遍历过程中如果有另外的线程对集合做结构变化,比如添加元素或者删除元素等操作。昨天在上线的过程中,发现了一个ConcurrentModificationException,异常抛出的位置是ArrayList.sort()。
代码分析
@Override
@SuppressWarnings("unchecked")
public void sort(Comparator<? super E> c) {
final int expectedModCount = modCount;
Arrays.sort((E[]) elementData, 0, size, c);
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
modCount++;
}
在排序之前,获取modCount的值,在排序之后,再次比对看这个值有没有发生变化,如果发生变化,抛出ConcurrentModificationException;如果没有发生变化,modCount加1。那么在并发排序的情况下,就会出现t1和t2同时对这个list进行排序,如果t2先完成排序,发现modCount的值没有变化,就会对modCount进行+1,等到t1执行完排序后,发现modCount的值发生变化,那么就会抛出ConcurrentModificationException。
这个modCount的语义什么?
这个字段是定义在AbstractList中的,官方文档上说这个字段的值是用来记录这个list的被修改次数,这里的修改指的是结构变化,改变了list的size,用来做fast-fail的。