pujan jain
pujan jain

Reputation: 169

What is the logic of a fail safe iterator?

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

Upvotes: 9

Views: 1349

Answers (1)

Stuart Marks
Stuart Marks

Reputation: 132450

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.

Upvotes: 13

Related Questions