当前位置:网站首页>Fail fast and fail safe

Fail fast and fail safe

2022-06-10 17:00:00 Zhangzhiming (hard work version)

fail-fast( Fast failure )
        When we're traversing the set elements , Iterators are often used , But in the process of iterators traversing elements , If the structure of the set is changed , Will throw an exception , Prevent further traversal . This is the so-called fast failure mechanism . namely : Once the traversal is found, others will modify Throw the exception immediately .java.util All collection classes below the package fail quickly

      We can iterate through list,Iterator It's an interface ,  ArrayList Internal class implementation Iterator Interface to implement related methods The code is as follows among expectedModCount It records the initial use of Iterator Ergodic time ArrayList Modified several times If there is 4 Elements Then it is modified 4 Time   expectedModCount=4; Calling next() When the method moves to the next element   Must be called first checkForComodification() Inspection ;  modCount != expectedModCount  These two values are equal at first All are 4  -->int expectedModCount = modCount;
        If the iterator is traversing the element , If modCount This value has changed , Then an exception will be thrown when traversing again . When we change the number of elements in the set ,modCount The value of will be changed , If you remove , Insert . But modification will not .

    private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        Itr() {}

        public boolean hasNext() {
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        @Override
        @SuppressWarnings("unchecked")
        public void forEachRemaining(Consumer<? super E> consumer) {
            Objects.requireNonNull(consumer);
            final int size = ArrayList.this.size;
            int i = cursor;
            if (i >= size) {
                return;
            }
            final Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length) {
                throw new ConcurrentModificationException();
            }
            while (i != size && modCount == expectedModCount) {
                consumer.accept((E) elementData[i++]);
            }
            // update once at end of iteration to reduce heap write traffic
            cursor = i;
            lastRet = i - 1;
            checkForComodification();
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }


fail-safe  ( Security failure )
         When we make changes to the set structure , To adopt fail-safe In terms of mechanism , Does not throw an exception . namely : Find someone else to modify while traversing There should be coping strategies For example, sacrificing consistency to make the whole traversal run complete , This is because when the structure of the set is changed ,fail-safe The mechanism will copy a piece of data from the original set , Then traverse the copied data
        java.util.concurrent The containers under the package are all security failures , It can be used concurrently in multithreading , Concurrent modification .

         A fast failing iterator throws ConcurrentModificationException abnormal , The iterator of security failure will never throw such an exception .
        
shortcoming :

  1. Replication requires extra space and time overhead .
  2. Because the traversal and addition operations are different arrays , So there is no guarantee that you will be traversing the latest content .

​​​​​​​copyOnWritearraylist Source code :
       
Calling add When the method is used Object[] newElements = Arrays.copyOf(elements, len + 1);

   public boolean add(E e) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();
            int len = elements.length;
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            newElements[len] = e;
            setArray(newElements);
            return true;
        } finally {
            lock.unlock();
        }
    }

 

原网站

版权声明
本文为[Zhangzhiming (hard work version)]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/161/202206101600053435.html