Fail Fast vs Fail Safe in Java

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.

The only difference is fail safe iterator doesn’t throw any Exception but fail-fast Iterator. A collection is modified structurally while one thread is iterating over it, because the modification happens on clone of a collection instead of original collection and that’s why they are called as fail-safe iterators.

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

Iterators in Java allow you 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

The following Java code shows how fail-fast iterator works.

package com.roytuts.java.fail.fast.fail.safe;

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

public class FailFastExample {

    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

Running the above program will give you the following example:

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

Apple => iOS
Google => Android
Microsoft => Windows
RedHat => Unix
Exception in thread "main" java.util.ConcurrentModificationException
	at java.base/java.util.TreeMap$PrivateEntryIterator.nextEntry(TreeMap.java:1208)
	at java.base/java.util.TreeMap$KeyIterator.next(TreeMap.java:1262)
	at com.roytuts.java.fail.fast.fail.safe.FailFastExample.main(FailFastExample.java:34)

Fail Safe Example

The following Java code shows an example on fail safe iterator.

package com.roytuts.java.fail.fast.fail.safe;

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

public class FailSafeExample {

    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

Running the above program will give you the following output:

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

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

Source Code

Download

Leave a Reply

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