A system is called fail-fast if it stops immediately its execution when an error occurred. The system does not continue with the errors and these errors in the fail-fast systems are immediately exposed. But, fail-safe system does the opposite thing. The fail-safe system does not stop its execution despite an error or a fault is occurred in the system. The system continues with the operations hiding the errors instead of exposing the errors immediately.

From one of the javadoc in HashMap

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.

Fail Fast and fail Safe Iterators in Java

Iterators in Java allow us to iterate through the Collection objects for traversing the elements in the Collection objects. Iterators returned by the Collection are either fail-fast or fail-safe in nature. The only difference is fail-safe iterator doesn’t throw any exception, contrary to fail-fast Iterator, if a Collection is modified structurally while one thread is iterating over it. This is because the Iterator works on clone of Collection instead of original collection and that’s why it is called as fail-safe iterator. That’s why fail-safe iterators require extra memory to clone the collection, whereas fail-fast iterators don’t require extra memory. Iterator of CopyOnWriteArrayList is an example of fail-safe Iterator and also iterator written by ConcurrentHashMap keySet is also fail-safe iterator and never throw ConcurrentModificationException in Java. But Iterators of ArrayList, HashMap etc. are fail-fast iterators.

Fail Fast example

package com.roytuts.collections;

import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

public class TreeMapExample {

    public static void main(String[] args) {
        Map<String, String> llMap = new TreeMap<>();
        llMap.put("RedHat", "Unix");
        llMap.put("Google", "Android");
        llMap.put("Apple", "iOS");
        llMap.put("Microsoft", "Windows");

        // iterate over HashMap
        llMap.forEach((k, v) -> System.out.println(k + " => " + v));

        System.out.println();

        // iterate using iterator
        Iterator<Entry<String, String>> iterator = llMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<java.lang.String, java.lang.String> entry = (Map.Entry<java.lang.String, java.lang.String>) iterator
                    .next();
            System.out.println(entry.getKey() + " => " + entry.getValue());
        }

        Set<String> keys = llMap.keySet();
        for (Object key : keys) {
            llMap.remove(key); // it will throw the ConcurrentModificationException here
            llMap.put("abc", "value"); // it will throw the
                                        // ConcurrentModificationException here
        }
    }

}

Output

Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.TreeMap$PrivateEntryIterator.nextEntry(TreeMap.java:1211)
	at java.util.TreeMap$KeyIterator.next(TreeMap.java:1265)
	at com.roytuts.collections.TreeMapExample.main(TreeMapExample.java:32)
Apple => iOS
Google => Android
Microsoft => Windows
RedHat => Unix

Apple => iOS
Google => Android
Microsoft => Windows
RedHat => Unix

Fail Safe example

package com.roytuts.collections;

import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class ConcurrentHashMapExample {

    public static void main(String[] args) {

        ConcurrentMap<String, String> cMap = new ConcurrentHashMap<>();
        cMap.put("RedHat", "Unix");
        cMap.put("Google", "Android");
        cMap.put("Apple", "iOS");
        cMap.put("Microsoft", "Windows");
        cMap.putIfAbsent("RedHat", "Unix");

        cMap.forEach((k, v) -> System.out.println(k + " => " + v));
        
        Set<String> keys = cMap.keySet();
        for (Object key : keys) {
            //cMap.remove(key); //will not throw ConcurrentModificationException here
            cMap.put("abc", "value"); //will not throw ConcurrentModificationException here
        }
        
        System.out.println();
        
        cMap.forEach((k, v) -> System.out.println(k + " => " + v));
    }

}

Output

RedHat => Unix
Google => Android
Apple => iOS
Microsoft => Windows

RedHat => Unix
Google => Android
Apple => iOS
abc => value
Microsoft => Windows

Thanks for reading.

Tags:

I am a professional Web developer, Enterprise Application developer, Software Engineer and Blogger. Connect me on Roy Tutorials | TwitterFacebook Google PlusLinkedin | Reddit

Leave a Reply

Your email address will not be published. Required fields are marked *