fail-fast fast failure mechanism and fail-safe safety failure mechanism

**

Definition of fail-fast fast failure mechanism

**
An error mechanism in java collection (Collection). When multiple threads operate on the contents of the same collection, a fail-fast event may occur. For example: when a thread A traverses a collection through iterator, if the content of the collection is changed by other threads; then when thread A accesses the collection, a ConcurrentModificationException will be thrown and a fail-fast event will be generated.
**

Fail-fast fast failure mechanism

**
1. In the case of a single thread, when using an iterator to traverse objects, the structure of the collection is modified (add, delete, modify elements)

      ArrayList<Integer> integers=new ArrayList<Integer>();
        integers.add(2);
        integers.add(1);
        integers.add(null);

        Iterator iterator=integers.iterator();
        while (iterator.hasNext()){
    
    
            Integer value= (Integer) iterator.next();
            if (value.equals(2)){
    
    
                integers.remove(value);
            }
            //integers.add(1);
    

        }

Insert picture description here
2. In a multithreaded environment, if the collection object is modified concurrently, ConcurrentModificationException will be thrown.

Reasons for fail-fast fast failure mechanism

Take ArrayList as an example, look
at the parent class AbstractList of ArrayList and Iterator source code ArrayList defines a modCount

    /**
     * The number of times this list has been <i>structurally modified</i>.
     * Structural modifications are those that change the size of the
     * list, or otherwise perturb it in such a fashion that iterations in
     * progress may yield incorrect results.
     *
     * <p>This field is used by the iterator and list iterator implementation
     * returned by the {@code iterator} and {@code listIterator} methods.
     * If the value of this field changes unexpectedly, the iterator (or list
     * iterator) will throw a {@code ConcurrentModificationException} in
     * response to the {@code next}, {@code remove}, {@code previous},
     * {@code set} or {@code add} operations.  This provides
     * <i>fail-fast</i> behavior, rather than non-deterministic behavior in
     * the face of concurrent modification during iteration.
     *
     * <p><b>Use of this field by subclasses is optional.</b> If a subclass
     * wishes to provide fail-fast iterators (and list iterators), then it
     * merely has to increment this field in its {@code add(int, E)} and
     * {@code remove(int)} methods (and any other methods that it overrides
     * that result in structural modifications to the list).  A single call to
     * {@code add(int, E)} or {@code remove(int)} must add no more than
     * one to this field, or the iterators (and list iterators) will throw
     * bogus {@code ConcurrentModificationExceptions}.  If an implementation
     * does not wish to provide fail-fast iterators, this field may be
     * ignored.
     */
    protected transient int modCount = 0;//记录list修改次数

The ArrayList iterator defines an expectedModCount=modCount.
Insert picture description here
When using the iterator to access the collection object, if the collection structure is modified, it will make modCount+1, making expectedModCount!==modCount, thus reporting ConcurrentModificationException.
Insert picture description here

Insert picture description here
Note that the fast-failure behavior of iterators cannot be guaranteed, because generally speaking, it is impossible to make any hard guarantees about whether asynchronous concurrent modifications occur. The fail fast iterator will do its best to throw ConcurrentModificationException. Therefore, it is wrong to write a program that relies on this exception in order to improve the correctness of this type of iterator: the fast failure behavior of iterators should only be used to detect bugs.

Fail-fast fast failure mechanism solution

1. Add the synchronized keyword in the method of using modCount, but it is not recommended that the synchronization lock caused by addition and deletion may block the traversal operation
. 2. Replace ArrayList with CopyOnWriteArrayList. It is recommended to use this scheme
CopyOnWriteArrayList. The difference from ArrayList is that all variable operations of CopyOnWriteArrayList are implemented by a new copy of the original array, so it is thread-safe, and CopyOnWriteArrayList will not report ConcurrentModificationException when modifying the structure in the iterator. The overhead caused by the class is relatively large (array copy). But it is very applicable in both cases.
1. When you cannot or do not want to perform synchronization traversal, but you need to eliminate conflicts from concurrent threads. 2. When the number of traversal operations greatly exceeds the number of variable operations.

  Iterator<Integer> iterator2=copyOnWriteArrayList.iterator();
        while (iterator2.hasNext()){
    
    
            int value=iterator2.next();
            copyOnWriteArrayList.add(1);
        }

Definition of fail-safe safety failure mechanism

Fail-safe Any modification to the collection structure will be modified on a copied collection, so ConcurrentModificationException will not be thrown. The CopyOnWriteArrayList above is a fail-safe mechanism, and ConcurrentHashMap is also a fail-safe mechanism
. The advantage of fail-safe is that it will not Reporting ConcurrentModificationException The
disadvantages are (1) the collection needs to be copied, resulting in a large number of invalid objects, which is expensive
(2) it is impossible to guarantee that the data read is the data in the current original data structure.

Guess you like

Origin blog.csdn.net/rj2017211811/article/details/109175925