先看怎么发生java
List<Integer> list=new ArrayList<>(); for(int i=0;i<10;i++){ list.add(i); } Iterator<Integer> it=list.iterator(); while(it.hasNext()){ Integer str=it.next(); if(str==5) list.remove(str);//不经过it.remove()方法删除,而是经过list.remove()方法删除元素 }
这段代码,就会发生java.util.ConcurrentModificationException异常
一下看看实现:
先看 AbstractList 类有这样一个变量安全
/** * The number of times this list has been <i>structurally modified</i>. * Structural modifications are those that change the size of the * list, or otherwise perturb it in such a fashion that iterations in * progress may yield incorrect results. * 他表明list被修改的次数(通常指 add,remove 次数。某个元素重赋值,通常不计数 ) * <p>This field is used by the iterator and list iterator implementation * returned by the {@code iterator} and {@code listIterator} methods. * If the value of this field changes unexpectedly, the iterator (or list * iterator) will throw a {@code ConcurrentModificationException} in * response to the {@code next}, {@code remove}, {@code previous}, * {@code set} or {@code add} operations. This provides * <i>fail-fast</i> behavior, rather than non-deterministic behavior in * the face of concurrent modification during iteration. * 这个变量,通常在是 iterator , list iterator 实现时用到的,而且在他们的 next,remove,add,previous 等方法中,会利用它决定是否抛出ConcurrentModificationException异常。 * <p><b>Use of this field by subclasses is optional.</b> If a subclass * wishes to provide fail-fast iterators (and list iterators), then it * merely has to increment this field in its {@code add(int, E)} and * {@code remove(int)} methods (and any other methods that it overrides * that result in structural modifications to the list). A single call to * {@code add(int, E)} or {@code remove(int)} must add no more than * one to this field, or the iterators (and list iterators) will throw * bogus {@code ConcurrentModificationExceptions}. If an implementation * does not wish to provide fail-fast iterators, this field may be * ignored. * 也能够在子类中利用这个字段,提供快速失败机制。具体在像add,remove方法中,增长modCount的值,每次调用加1。而后利用它,决定是否抛出ConcurrentModificationExceptions */ protected transient int modCount = 0;
接着看ArrayList类方法多线程
/** * Returns an iterator over the elements in this list in proper sequence. * 这个方法,返回一个自己list的一个iterator * <p>The returned iterator is <a href="#fail-fast"><i>fail-fast</i></a>. * * @return an iterator over the elements in this list in proper sequence */ public Iterator<E> iterator() { return new Itr();//关键这个类 }
再看 Itr类ide
/** * An optimized version of AbstractList.Itr */ private class Itr implements Iterator<E> { int cursor; // index of next element to return //有个潜台词,默认值是0,list当前的下标 int lastRet = -1; // index of last element returned; -1 if no such int expectedModCount = modCount;//初始化时候,会把list原来的修改次数,赋给expectedModCount public boolean hasNext() { return cursor != size; } @SuppressWarnings("unchecked") public E next() { checkForComodification();//会抛出java.util.ConcurrentModificationException异常 int i = cursor; if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1;//每次,移动下标加1,下次的游标位置 return (E) elementData[lastRet = i];//lastRet 赋值本次的坐标。 } public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification();//会抛出java.util.ConcurrentModificationException异常 try { ArrayList.this.remove(lastRet);//根据下标删除元素,ArrayList.this.remove()方法,会modCount++; cursor = lastRet; lastRet = -1; expectedModCount = modCount;//让后又把最新的modCount 赋给expectedModCount,这样保证,经过Itr remove方法删除元素,不会抛ConcurrentModificationException异常,由于expectedModCount == modCount } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } final void checkForComodification() {//抛出java.util.ConcurrentModificationException异常的方法 if (modCount != expectedModCount)//若是modCount 不等于expectedModCount 就抛出这个异常 throw new ConcurrentModificationException(); } }
最后,再回来讲ConcurrentModificationException异常,直接一点,它的做用是,一个集合(list 实现,好比ArrayList,LinkedList,Vertor 等AbstractList子类),
在用它本身的Iterator对象 在玩转它自己时(next,remove,add,previous 调用)时,若是发现有其余方式(非这个Iterator 对象),
修改这个list对象,就会(经过比较modCount, expectedModCount值)抛出ConcurrentModificationException异常。因为 Iterator 对象不是线程安全的,在多线程中用it.remove()删除元素,一样能够抛出 ConcurrentModificationException异常 !this