java fail-fast机制

2022-07-27,,,

概述

fail-fast 机制java集合(Collection)中的一种错误机制。当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件。例如:当某一个线程A通过iterator去遍历某集合的过程中,若该集合的内容被其他线程所改变了;那么线程A访问集合时,就会抛出ConcurrentModificationException异常,产生fail-fast事件。

该机制设计的初衷

在遍历集合元素的过程中,是不希望集合被修改的;不然会产生许多问题,比如:
arraylist在遍历的过程中,元素被删除。此时后面的元素会进行移位,来填补空出来的位置;元素移位不是原子操作,相反元素较多的情况下,这个过程消耗的时间不短;元素位置调整的过程中,又进行遍历,肯定会产生不少问题,比如漏掉对元素的访问。
为此只要检测到集合被修改过,就应该快速的失败,并抛出异常。

该机制的实现

每个集合类都有一个成员变量,private transient int modCount = 0;
从字面意思代表集合被修改的次数,实际上就是代表数据的版本。每进行一次修改集合的操作(比如,list中的add,remove;map中的put等),modCount的值加一。
以Arraylist的代码为例:

    public boolean add(E e) {
        modCount++;
        add(e, elementData, size);
        return true;
    }

当遍历集合的时候,会用expectedModCount来保存modCount,然后每次访问元素的时候,都会判断两者是否相等,来检查集合是否被修改过。下面是ArrayList创建的迭代器。

    public Iterator<E> iterator() {
        return new Itr();
    }
    // Itr是内部类,可以访问到ArrayList的成员变量
    // 代码有删除
    private class Itr implements Iterator<E> {
        // modCount是ArrayList的成员变量,创建Itr会存储当前modCount
        // 后续遍历元素时,通过对比两者来判断集合是否修改过
        int expectedModCount = modCount;
        @SuppressWarnings("unchecked")
        public E next() {
            // 判断集合是否修改过
            checkForComodification();
            int i = cursor;
            Object[] elementData = ArrayList.this.elementData;
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }
        // iterator自己修改集合不会产生问题,因为调用者清楚自己在干啥
        // 删除元素的同时修改modCount,这样同时创建出来的两个迭代器,
        // 一个修改后,另外一个能够感知到
        public void remove() {
            ArrayList.this.remove(lastRet);
            cursor = lastRet;
            lastRet = -1;
            expectedModCount = modCount;
        }
        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

本文地址:https://blog.csdn.net/shuxiaohua/article/details/110234740

《java fail-fast机制.doc》

下载本文的Word格式文档,以方便收藏与打印。