简体   繁体   中英

How Java iterators detect the collection is modified to throw ConcurrentModificationException?

How Java iterators detect the collection is modified? Tried to search, found:

Usually the traditional collection classes in java.util package uses an int variable (modCount) to keep track of modifications (additions and deletions).

When we ask for an Iterator from these collection classes then a object of Iterator which is returned is provided with the existing modification count variable as its expected modification count.

Upon invoking the next() method the Iterator object checks the current modification count variable value against its expected modification count value.

In case of a mismatch it fails fast by throwing ConcurrentModificationException present in java.util package, its a RuntimeException.

But what if we

  1. Postpone the iterator before modification
  2. Modify the collection
  3. create 2nd iterator after modification happened and iterate

?

It seems everything OK with 2nd iterator, isn't it? So how about modCount then? The modified collection should inform the 1st iterator to throw the exception and at the same time shouldn't inform the 2nd. Explain please how modCount works? It should be challenge to program modCount's behavior or keep a collection of modCounts for each iterator. Anyway clarify please how multiple iterators validate their consistency simultaneously and independently?

Generally, it works like this:

class MyCollection implements Collection<E /* or whatever the elements are */> {
    private int modCount = 0;
    private class MyIterator implements Iterator<E> {
         private int expectedModCount;
         public MyIterator() {
              expectedModCount = modCount;
         }
         @Override
         public E next() {
             if(expectedModCount != modCount) throw new ConcurrentModificationException();
         }
         // etc.
    }
    @Override
    public Iterator<E> iterator() {
        return new MyIterator();
    }
    @Override
    public boolean add(E e) {
       modCount++;
       // etc.
    }
    // etc.
}

Each MyIterator knows what modCount to expect, remembering the value as a field. Your iterators 1 and 2 will not get confused, because they will be separate objects with separate fields with separate values, which means they will expect different modCount s. Further, note that ConcurrentModificationException s are thrown by "polling", not by "notification". The collection does not need to keep track of its iterators and notify them about modification when you call a method on the collection. Rather, each iterator checks whether the collection has been modified when you call a method on the iterator. If you never use an iterator after the collection has been modified, it will never get the chance to throw an exception, so, in your example, no exception will be thrown, and that is the correct behavior.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM