Search code examples
javacollectionsconcurrencyiteratorconcurrentmodification

What leads to ConcurrentModificationException


I was reading about ConcurrentModificationException. I found this piece of code for the iterator.Can anybody explain what actually leads to this exception.I just want some justification for the logic written below.

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

@SuppressWarnings("unchecked")
public E next() {
    checkForComodification();
    int i = cursor;
    if (i >= size)
        throw new NoSuchElementException();
    Object[] elementData = ArrayList.this.elementData;
    if (i >= elementData.length)
        throw new ConcurrentModificationException();
    cursor = i + 1;
    return (E) elementData[lastRet = i];
}

public void remove() {
    if (lastRet < 0)
        throw new IllegalStateException();
    checkForComodification();

    try {
        ArrayList.this.remove(lastRet);
        cursor = lastRet;
        lastRet = -1;
        expectedModCount = modCount;
    } catch (IndexOutOfBoundsException ex) {
        throw new ConcurrentModificationException();
    }
}

final void checkForComodification() {
    if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
    }
}

Solution

  • Your underlying number of elements are changing size while you are iterating over them so an exception is thrown.

    Note that the attempt here isn't to recover from an impossible situation, it is to "Fail" as early and cleanly as possible. It would probably be quite easy to not throw an exception and make something work, but the behavior is undefined. This is doing everything possible to make sure that you don't have a coding bug in your iterator, not just recover from an impossible code corner.

    // This line is getting the underlying array out from "this" ArrayList   
    Object[] elementData = ArrayList.this.elementData; 
    
    // I is the current value of your cursor.  Every time you call "next"
    // this cursor is being incremented to get the next value
    // This statement is asking if your current cursor extends beyond the
    // end of the array, if it does then "Something" happened to make the array
    // smaller while we weren't looking...
    if (i >= elementData.length) 
        // To indicate that the elementData array has changed size outside of
        // our current iterator, throw an exception to the user.
        throw new ConcurrentModificationException();
    

    So, to cause this to happen, you would create an iterator, then reduce the size of the array list, then call "Next". This should give you a CME