Ever wondered why some collections throw ConcurrentModificationException and others don't? Basically, iterators from java.util package throw ConcurrentModificationException if you change it while iterating over it but iterators from java.util.concurrent package do not.
If you check JDK you can easily figure out why!
We're talking about two different behaviours here: fail-fast and fail-safe!
Fail-fast behaviour fails as soon as it realizes that the Collection has been changed since the iteration began. Which means that if a thread is iterating over a Collection and you try to remove, add or update one element an exception will be thrown.
But how does this Collection know it has been changed? ArrayList, Vector and HashSet are examples of Collections with fail-fast behaviour and they all extend AbstractList. AbstractList keeps a variable set to 0 that is incremented whenever you update/add/remove your iterator. If you start iterating over it and meanwhile it realizes that modCount has changed, ConcurrentModificationException is thrown.
Fail-safe does not raise any exception because it iterates over a clone of the Collection you want to iterate rather than the original one. CopyOnWriteArrayList and ConcurrentHashMap are both examples of Collections with fail-safe behaviour. However, there are two major issues with fail-safe behaviour:
- Memory overhead to keep the Collections copy;
- No guarantee that the data is up to date since the original data stucture might be changed meanwhile.