Fail-Fast iterators :
Fail-fast iterators fail as soon as they realize that the structure of the collection has changed since the iteration has begun. By changing the structure of the collection, we mean adding, removing or updating an element in the collection. It is implemented by keeping a modification count and if the iterating thread realizes the change in modification count, it throws ConcurrentModificationException. Most of the collections in Java are fail-fast. This is not a guaranteed behavior. So, we should not rely on this behavior.We can get ConcurrentModificationException if one thread is iterating over a collection and at the same time that collection is modified by some other thread. Please note that we can get ConcurrentModificationException even in single threaded applications. The following code snippet would throw ConcurrentModificationException :
Whereas, the following code snippet won't throw ConcurrentModificationException :
So, if we use Iterator's remove method, we won't get ConcurrentModificationException. To understand why the second approach doesn't throw ConcurrentModificationException, we need to understand how fail-fast iterators are implemented in Java. The fail-fast iterators are typically implemented using a volatile counter on the list object. When the list is updated, the counter is updated. When an iterator is created, the current value of the counter is embedded in the Iterator object. When an iterator operation is performed, the iterator method compares the list counter with the Iterator counter, and throws ConcurrentModificationException if they differ. That explains why the first code snippet above throws ConcurentModificationException. On the contrary, if we use Iterator's remove method (second code snippet above), the Iterator counter is also decremented. So, in the next iteration, the counter check succeeds. Hence, the second code snippet above doesn't throw ConcurrentModificationException.