ConcurrentModificationException 异常的抛出

ConcurrentModificationException 异常是使用java集合类经常抛出的一种异常。

这种异常常被描述为:快速失败异常,一般是我们程序错误使用导致的,很少会故意允许这种异常发生已保证逻辑上的完整。

那下面讨论什么时候会发生这种异常呢? 以ArrayList为例!

1、单线程中,一边遍历(forEach 和 list.iterator()),一遍删增数据。



List<Integer> list = new ArrayList<Integer>();
for(int i=0;i<10;i++){
list.add(i);
}
for(int i: list){ //等同 list.iterator()的效果
list.add(i);
}



深层原因 还是看看源码吧,一切因缘都在源码之中:

private class Itr implements Iterator<E> {
/**
* Index of element to be returned by subsequent call to next.
游标 开始从0获取数据
*/
int cursor = 0;

/**
最近一次返回的数据的index,如果调用了remove ,那么返回-1
*/
int lastRet = -1;

/**
modCount 标识list结构改变的次数, modCount 是没有volitile 修饰的!!,所以在多线程环境中 这个逻辑有可能不会快速失败,
这也从另外一个方面证明:ArrayList压根就不能在线程不安全的环境中使用!!! 使用就是个错误!!

另外:expectedModCount 只有通过Iterator的 remove 方法操作 才会修改这个值,保证不会抛出ConcurrentModificationException ,
如果调用ArrayList的add 或者remove等修改底层结构的操作,那么expectedModCount != modCount 也就会发生ConcurrentModificationException 异常喽
*/
int expectedModCount = modCount;

public boolean hasNext() {
return cursor != size();
}

public E next() {
checkForComodification();
try {
E next = get(cursor);
lastRet = cursor++;//当前游标也要动动哦
return next;
} catch (IndexOutOfBoundsException e) { //为什么会抛出异常? 因为:checkForComodification()之后,可能立即有其他线程变动了底层的数组结构的(多线程环境下不安全的!!)
checkForComodification(); //一旦抛出此异常,可以认定会抛出checkForComodification异常喽!
throw new NoSuchElementException();
}
}

public void remove() {
if (lastRet == -1)
throw new IllegalStateException(); //如果连续remove两次,会有问题的,这里就是证据!!
checkForComodification();
try {
AbstractList.this.remove(lastRet);
if (lastRet < cursor)
cursor--; //cursor 为什么会 --?? 因为:ArrayList列表lastRet删除后,发送了数组的迁移复制。
lastRet = -1;
expectedModCount = modCount; //必须的,也是只有这里才能设置 expectedModCount
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}

//检测expectedModCount 和 modCount 是否一致,如果不一致可以认定,在迭代的过程中list发生了结构的改变
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}


2、如果另外一个线程调用了remove 或者 add 或者有类似效果的操作,那么当前iterator迭代 就会抛出ConcurrentModificationException异常。也有可能不抛出,想想为什么?因为modCount 不具备线程可见性,倒是可能会抛出 IndexOutOfBoundsException 异常!!


[b]基于以上分析,在多线程环境中,上面的各自问题就更容易发生! 可能更诡异。
甚至可以说就不需要考虑多线程的情况,因为ArrayList压根就不该在多线程使用!![/b]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值