007Java collection 012 fast failure mechanism and security failure mechanism

Note: This article is based on JDK1.8.

1. Fast failure mechanism

1.1 description

The fast failure mechanism, namely the fail fast mechanism, directly traverses the container. In the traversal process, once it is found that the structure of the collection has changed, it will throw a ConcurrentModificationException, resulting in traversal failure.

The collection classes under the java.util package are fast failure mechanisms. Common containers traversed by fail fast include ArrayList and HashMap.

The fail fast mechanism can not guarantee that exceptions will be thrown under unsynchronized modifications. It just throws them as best as possible. Therefore, this mechanism is generally used to detect bugs.

1.2 phenomena

Cases that trigger the fail fast mechanism:

 1 public static void main(String[] args) {
 2     List<String> list = new ArrayList<>();
 3     list.add("00");
 4     list.add("11");
 5     list.add("22");
 6     for (String s : list) {
 7         if ("00".equals(s)) {
 8             list.add("99");
 9         }
10     }
11 }

Note: only a common case is listed here. In fact, it will occur in List, Set and Map, and in both single threaded and multi-threaded environments.

1.3 reasons

The fail fast mechanism can occur in both single threaded and multi-threaded environments. If a change in the collection structure is detected in the iterative traversal process, it is possible to trigger and throw an exception.

To understand the fail fast mechanism, you need to check the logic of the underlying source code, because the principle of triggering the fail fast mechanism is the same. This paper takes ArrayList as an example.

To view the iterator method of ArrayList:

1 public Iterator<E> iterator() {
2     return new Itr();
3 }

Continuing to view the internal class Itr maintained by ArrayList, we need to focus on three properties:

 1 private class Itr implements Iterator<E> {
 2     int cursor;       // The index to be traversed when traversing the collection
 3     int lastRet = -1; // Record the index just traversed,-1 No, the last element does not exist
 4     int expectedModCount = modCount;// The initial value is modCount,Used to record the number of modifications to the collection
 6     public boolean hasNext() {
 7         return cursor != size;// Determine whether the traversal is over
 8     }
10     @SuppressWarnings("unchecked")
11     public E next() {
12         checkForComodification();// Check whether it is triggered fail-fast mechanism
13         int i = cursor;
14         if (i >= size)
15             throw new NoSuchElementException();
16         Object[] elementData = ArrayList.this.elementData;
17         if (i >= elementData.length)
18             throw new ConcurrentModificationException();
19         cursor = i + 1;
20         return (E) elementData[lastRet = i];
21     }
22     ...
23     final void checkForComodification() {
24         if (modCount != expectedModCount)
25             // expectedModCount If there is no change after initialization modCount An exception is thrown when a change occurs
26             throw new ConcurrentModificationException();
27     }
28 }

By analyzing the iterator source code, it can be found that the iterator's checkforconfirmation method is the key to judge whether to trigger the fail fast mechanism.

In the checkForComodification method, you can see whether to throw an exception depends on whether the modCount has changed.

Check the ArrayList source code and find that the change of modCount occurs in the modification of the collection, such as the add operation.

Therefore, when traversing a collection with an iterator, if the collection is modified at the same time, resulting in the change of modCount, the fail fast mechanism will be triggered and an exception will be thrown.

1.4 solution

1.4.1 using methods provided by iterators

In order to avoid triggering the fail fast mechanism, when iterating over the collection, you need to modify the collection using the modification method provided by the iterator.

1.4.2 using thread safe collection classes

You can also use thread safe collection classes, use CopyOnWriteArrayList instead of ArrayList, and use ConcerrentHashMap instead of HashMap.

2 security failure mechanism

2.1 description

The security failure mechanism, i.e. fail safe mechanism, traverses the cloned objects of the collection, and the modification of the collection will not affect the traversal operation.

The collection classes under the java.util.concurrent package fail safely and can be modified concurrently under multithreading. Common containers traversed by fail safe include CopyOnWriteArrayList and ConcerrentHashMap.

Traversal based on cloned objects avoids throwing a ConcurrentModificationException when modifying the collection, but it also leads to the inability to access the modified content during traversal.


Tags: Java

Posted on Thu, 02 Dec 2021 22:56:06 -0500 by kenyabob