Reputation: 43
Why are iterators called "fail-safe" and "fail-fast" even though Iterator.remove()
doesn't throw any ConcurrentModificationException
while iterating through a Collection
(for example, HashMap
) using Iterator
?
Upvotes: 0
Views: 1773
Reputation: 446
My answer includes two points.
Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs
Thus, you probably should take this behaviour into account when writing code, but you definitely must not fully rely on it.
concurrent modification policy
.So, there are four policies, and among them there is no fail-safe one:
The conclusion from the article says:
After all this, where does “fail-safe” come into the picture? Answer: it doesn’t. The words “fail-safe” are never used in the Java SE specifications that describe the concurrent modification policy of a collection. As such, there is no reliable, consistent definition of “fail-safe” for an Iterator. One can attempt to apply the general concept of “fail-safety” to an Iterator, but this is open to varying, misleading, and even contradictory interpretations.
Don’t use “fail-safe” to describe a Java Iterator. Instead, use one of the documented policies listed above.
Upvotes: 1
Reputation: 51
Upvotes: 0
Reputation: 989
As name suggest fail-fast Iterators fail as soon as they realized that structure of Collection has been changed since iteration has begun. Structural changes means adding, removing or updating any element from collection while one thread is Iterating over that collection. fail-fast behavior is implemented by keeping a modification count and if iteration thread realizes the change in modification count it throws ConcurrentModificationException.
Contrary to fail-fast Iterator, fail-safe iterator doesn't throw any Exception if Collection is modified structurally while one thread is Iterating over it because they work on clone of Collection instead of original collection and that’s why they are called as fail-safe iterator. Iterator of CopyOnWriteArrayList is an example of fail-safe Iterator also iterator written by ConcurrentHashMap keySet is also fail-safe iterator and never throw ConcurrentModificationException in Java.
Upvotes: 3
Reputation: 18304
Using Iterator.remove()
doesn't throw ConcurrentModificationException
, but if something else (in another thread) modifies the Collection
which backs the Iterator
during iteration, then it will.
From the Java API docs for java.util.ArrayList
; bold emphasis added by me:
The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a
ConcurrentModificationException
.
The next sentence of the same documentation then explains exactly what is meant by fail-fast in this case; again, bold emphasis added by me:
Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.
In other words, the simple and safe thing to do, if another thread modifies the collection, is to cause a deliberate, explicit failure in the form of ConcurrentModificationException
, rather than attempting to work out a non-failing, ie fail-safe, logic (such as having the modification show up via the Iterator
depending upon whether that element has already been iterated over) which could be complex and error-prone.
Upvotes: 4