Before moving forward let's understand Iterators and what is the reason for having fail-fast and fail-safe iterators. Iterators in Java are part of the Collection Framework. An iterator is an object that allows you to traverse through the elements of a collection (like a List, Set, or Map) sequentially, without exposing the underlying details of the collection's implementation. It provides a uniform way to access elements regardless of the specific type of collection.
Concurrent Modification
Concurrency in Java refers to the simultaneous execution of multiple threads or tasks. Concurrent modification occurs when one thread attempts to modify an object while another thread is actively accessing or modifying the same object. In simple terms, it involves altering an object while another task is in progress. This simultaneous modification can lead to changes in the structure of a data collection, involving actions such as adding, removing, or updating elements within the collection.
Now let's see fail-fast and fail-safe iterators
Fail-fast Iterator
Fail-fast iterator throws "ConcurrentModificationException" when one thread is iterating over a collection object and another thread structurally modifies the collection either by adding, removing, or modifying objects on the underlying collection. They are called fail-fast because they try to immediately throw Exceptions when they encounter failure.
Consider an example:
ArrayList<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Orange");
Iterator<String> iterator = fruits.iterator();
fruits.add("Grapes");
while (iterator.hasNext()) {
String fruit = iterator.next();
System.out.println(fruit);
}
Output
Exception in thread "main" java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1013)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:967)
at IteratorEx.main(IteratorEx.java:14)
In this example, we are first assigning the ArrayList to the iterator and then we are adding to the ArrayList. So, this will throw an exception here.
Fail-safe Iterator
A fail-safe iterator doesn't throw any Exception if a collection is modified structurally while one thread is iterating over it because it works on a clone of the collection instead of the original collection and that's why they are called a fail-safe iterator.
In order to avoid the exception we have to use fail-safe collection e.g. CopyOnWriteArrayList, ConcurrentHashMap. However, the drawback of using this collection is that they use extra memory for cloning of collection.
Consider an example:
CopyOnWriteArrayList<String> fruits = new CopyOnWriteArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Orange");
Iterator<String> iterator = fruits.iterator();
fruits.add("Grapes");
while (iterator.hasNext()) {
String fruit = iterator.next();
System.out.println(fruit);
}
Output
Apple
Banana
Orange
Here we can see that it didn't throw any exception.
In conclusion, the primary difference between fail-safe and fail-fast iterators lies in their response to concurrent modifications during iteration. A fail-safe iterator avoids throwing exceptions by operating on a cloned copy of the collection. In contrast, a fail-fast iterator promptly detects and throws a 'ConcurrentModificationException' if the collection is modified during iteration. Both approaches offer different trade-offs in terms of safety and performance, and the choice depends on the specific requirements of the application.
Comments