If fail-safe iterator creates a separate copy and works on that, how come it is aware of any changes made to the original?
public class concurrentHashMap {
There is no such thing as a "fail-safe" iterator in Java. At least, the Java SE specifications do not define such a term. I therefore recommend that you avoid using the term "fail-safe" to describe Java iterators.
I'm well aware that various articles on the Internet and elsewhere on Stack Overflow use the term "fail-safe", but their usage is not definitive, and it's likely to be incorrect or at the very least misleading. I believe you've been misled by such documentation.
It sounds like you read somewhere that a "fail-safe" iterator works on a separate copy. In your example, you use a ConcurrentHashMap
, which indeed has iterators that aren't fail-fast. However, CHM's iterators don't operate on a copy. Instead, they have semantics that are described by the official specification as weakly consistent. The definition is somewhat abstruse, but essentially, any element reported by such an iterator is guaranteed to have existed in the collection at some point in time. These kind of iterators might or might not reflect changes to the collection that were made after the iteration started. That's why the thread that's running the iterator sees changes made by the other thread. (It's also possible for some or none of the changes to be visible, since these threads have a data race.)
An example of another collection whose iterators are not fail-fast is CopyOnWriteArrayList. This collection's iterators operate on a snapshot, so any subsequent changes to the collection are never visible via an iterator.
For completeness, here is the definition of a fail-fast iterator from the ArrayList
specification. Most of the other (non-concurrent) collections in Java have a fail-fast iteration policy that's defined similarly.