Collection报ConcurrentModificationException错误的原因

某个线程在 Collection 上进行迭代时,通常不允许另一个线性修改该 Collection。
通常在这些情况下,迭代的结果是不确定的。如果检测到这种行为,一些迭代器实现(包括 JRE 提供的所有通用 collection 实现)可能选择抛出ConcurrentModificationException异常。
那Collection类是怎么检测这种情况呢?看了一下源码,发现jdk实现起的逻辑也很简单。
第一步:声明一个变量作为信号量
modCount属性相当于这个Collection的版本号;
第二步:维护这个信号量
例如在:remove()、add()、addAll()...执行时都要执行modCount++;
第三步:生成快照
在遍历Collection,会执行iterator()(jdk1.5后出现的循环新写法,遍历之前也会默认执行),而iterator()方法会把modCount复制到expectedModCount;
第四步:遍历检查
iterator()的对象在每次改动前会检查expectedModCount和modCount是否相等,如果相同说明Collection没有发生变化,如果不相同,则说明Collection发生了变化,抛出ConcurrentModificationException。
知道异常发生的原因问题就很好解决了。
具体解决方法分两种
1.加锁保证iterator()后的Collection没有其他线程进行改动;
2.原有的Collection复制一份,至于是复制成Array或使用CopyOnWriteArrayList复制,这个就可以根据项目要求选择了,然后操作这个复制的对象。
解决方法归结为:避免改动iterator()后的对象。