What is the difference between a failfast iterator and failsafe in JAVA?

1

My question is more conceptual, I have been looking for answers on this question but I am not understanding them. What is the difference and what do they mean in each case? Can you give examples? Thanks.

    
asked by Jorge Gonzalez 03.12.2017 в 16:36
source

1 answer

3

The difference is the behavior that they have in front of the concurrent modification.

Before you start, keep in mind that the implementation of these behaviors depends on each class and is not common, so the following is in general terms:

What is fail-fast ?

Fail-fast is a behavior of the Iterator of a collection. It implies that the Iterator checks aggressively that the underlying collection has not been modified since it started to iterate , and in Java the ConcurrentModificacionException .

Imagine you have two threads acting on a list. The first one is dedicated to reading it, and the second modifies it. If the Iterator of the first one has fail-fast behavior, each time you call methods that advance the position of the Iterator it is checked that the list has not been modified. In our example, the second thread has modified the list, so the exception will be thrown.

How is it implemented in Java?

Fail-fast is implemented with a change counter . The collection has this counter and its value is passed to Iterator . When you call the methods that advance the position, the Iterator checks that the values of the counters do not differ. If they differ, the exception is thrown.

An example

The non-concurrent collections of the JDK are an example of fail-fast although in the documentation of the classes that implement it is clearly specified that this behavior is not assured .

An example with ArrayList :

List<Integer> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);

Iterator<Integer> iterator = numbers.listIterator();        
while (iterator.hasNext()) {
    System.out.println(iterator.next());
    numbers.add(4);  // Modificacion de la lista mientras se itera
}

Output:

1
Exception in thread "main" java.util.ConcurrentModificationException
    at 
java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:937)
    at java.base/java.util.ArrayList$Itr.next(ArrayList.java:891)
    at SOE.Main.main(Main.java:12)

What is fail-safe ?

Fail-safe is another behavior of Iterator . This behavior implies that the Iterator is protected from concurrent modifications, and however much the underlying collection is modified, the iteration will not be affected and no exception will be thrown. .

In our example, the Iterator of the first thread would not be affected by the modifications of the second thread and your program would continue running without exceptions.

How is it implemented in Java?

This is a bit more complicated, because the fail-safe behavior does not appear in the Java documentation. The closest thing is the weak consistency . The way in which this is usually implemented is that the Iterator operates on a copy of the underlying collection, created at the time of creation of Iterator . In this way, all modifications made to the original collection will not affect your iteration.

An example

Collections of java.util.concurrent usually apply this behavior. An example with ConcurrentHashMap :

ConcurrentMap<String,String> capitales = new ConcurrentHashMap<>();
capitales.put("España", "Madrid");
capitales.put("Francia", "Paris");
capitales.put("Alemania", "Berlin");

Iterator<String> iterator = capitales.keySet().iterator();  // Se crea una copia

while (iterator.hasNext()) {
    System.out.println(capitales.get(iterator.next()));
    capitales.put("Inglaterra", "Londres");  // Modificacion del map mientras se itera
}

And the output:

Paris
Madrid
Berlin

Interestingly, if you try to put as keys of a ConcurrentMap integers, the modification is done. I suppose this has to do with the hashing and that the implementation of ConcurrentHashMap allows the concurrent modification with certain types of keys.

In any case, this should serve as an example of what I put at the beginning: The implementations depend on each class and to know them in depth you should read the documentation and the source code.

    
answered by 07.12.2017 / 08:53
source