make - is listiterator fail safe




What is the logic of a fail safe iterator? (4)

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 {
    public static void main(String[] args) throws InterruptedException {
        MapCheck obj1 = new MapCheck();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                obj1.put();
            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                obj1.iterte();
            }
        });

        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }
}

class MapCheck {
    Map<Integer,String> map = new ConcurrentHashMap<>();
    {
        map.put(1, "pujan");
        map.put(2, "manish");
        map.put(3, "swati");
    }

    void iterte() throws InterruptedException {
        for (int key : map.keySet()) {
            Thread.sleep(2000);
            System.out.println(map.get(key));
        }
    }

    void put() throws InterruptedException{
        Thread.sleep(2000);
        map.put(1, "pujan1");
        map.put(2, "manish1");
        map.put(3, "swati1");
    }
}

The output is:

pujan1
manish1
swati1

The only difference is fail-safe iterator doesn't throw any Exception, contrary to fail-fast Iterator.

If Collection is modified structurally while one thread is iterating over it. This is 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.


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 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.


What are fail-safe & fail-fast Iterators in Java

What is the difference between them ...

"Fail safe" means: it won't fail. Strictly speaking, there is no such thing in Java as a fail-safe iterator. The correct term is "weakly consistent". The javadoc says:

"Most concurrent Collection implementations (including most Queues) also differ from the usual java.util conventions in that their Iterators and Spliterators provide weakly consistent rather than fast-fail traversal."

Typically, weak consistency means that if a collection is modified concurrently with an iteration, the guarantees of what the iteration sees are weaker. (The details will be specified in each conncurrent collection classes javadocs.)

"Fail fast" means: it may fail ... and the failure condition is checked aggressively so that the failure condition is (where possible1) detected before damage can be done. In Java, a fail-fast iterator fails by throwing a ConcurrentModificationException.

The alternative to "fail-fast" and "weakly consistent" is a semantic where the iteration fails unpredictably; e.g. to sometimes give the wrong answer or throw a totally unexpected exception. (This was the behavior of some standard implementations of the Enumeration API in early versions of Java.)

... and are they different from the iterator we use for collection.

No. These are properties of the iterators implemented by standard Collection types; i.e. they are either "fail fast" or "weakly consistent" ... when used correctly with respect to synchronization and the Java memory model1.


The fail-fast iterators are typically implemented using a volatile counter on the collection object.

  • When the collection is updated, the counter is incremented.
  • When an Iterator is created, the current value of the counter is embedded in the Iterator object.
  • When an Iterator operation is performed, the method compares the two counter values and throws a CME if they are different.

The implementation of fail-safe iterators is typically light-weight. They typically rely on properties of the specific list implementation's data structures. There is no general pattern. (Read the source code for the specific collection classes you are interested in.)


1 - The rider is that fail-fast behavior assumes that the application id correctly with respect to synchronization and the memory model. That means that (for example) if you iterate an ArrayList without proper synchronization, the end result could be a corrupted list result. The "fast fail" mechanism will probably detect the concurrent modification (though that isn't guaranteed), but it won't detect the underlying corruption. As an example, javadoc for Vector.iterator() says this:

"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."


What is the logic of a fail safe iterator?

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 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.