美文网首页
Java fail-fast 和 fail-safe机制

Java fail-fast 和 fail-safe机制

作者: ObadiObada | 来源:发表于2017-10-30 18:38 被阅读0次

    Java fail-fast 和 fail-safe机制

    基本概念

    fail-fastfail-safe这两个概念都是和集合的并发修改相关的。集合的并发修改是指:当一个线程正在遍历集合时,当另外 一个线程(或线程本身)修改了集合。

    fail-fast

    fail-fast 机制是指在遍历集合的过程中如果发现了集合被改变,则抛出ConcurrentModificationException。通常有如下两种情况:

    1. 遍历集合过程中本修改了集合
    2. 多线程的情况下,本线程遍历集合过程中,其他线程修改了集合。

    fail-fast的检测

    以ArrayList代码为例,从代码可以看出expectedModCount初始化为modCount, 其中modeCount是ArrayList被修改(add remove)的次数,iterator next 以及remove接口 都会检查expectedModCount和modCount是否相等,如果不等则抛出异常。

    public Iterator<E> iterator() {
        return new Itr();
    }
    
    private class Itr implements Iterator<E> {
        protected int limit = ArrayList.this.size;
    
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;
    
        public boolean hasNext() {
            return cursor < limit;
        }
    
        @SuppressWarnings("unchecked")
        public E next() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    
        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }
    
    

    一个例子:

    ArrayList<String> list = new ArrayList<String>();
    list.add("A");
    list.add("B");
    list.add("C");
    for (String str : list) {
        list.add("D") ;
    }
    

    输出结果:

    Exception in thread "main" java.util.ConcurrentModificationException

    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)

    at java.util.ArrayList$Itr.next(ArrayList.java:851)

    at TestJava.main(TestJava.java:14)

    这里隐含了一个知识点,对于foreach循环,javac编译器实际上是将其处理成iterator迭代。

    fail-safe

    fail-safe 机制是指在遍历集合的过程中如果发现了集合被改变,遍历集合依然可以正常进行,以CopyOnWriteArrayList为例:

    public Iterator<E> iterator() {
        return new COWIterator<E>(getArray(), 0);
    }
    
    static final class COWIterator<E> implements ListIterator<E> {
        /** Snapshot of the array */
        private final Object[] snapshot;
        /** Index of element to be returned by subsequent call to next.  */
        private int cursor;
    
        COWIterator(Object[] elements, int initialCursor) {
            cursor = initialCursor;
            snapshot = elements;
        }
        //...
    }
    
    public boolean add(E e) {
        synchronized (lock) {
            Object[] elements = getArray();
            int len = elements.length;
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            newElements[len] = e;
            setArray(newElements);
            return true;
        }
    }
    
    public E remove(int index) {
        synchronized (lock) {
            Object[] elements = getArray();
            int len = elements.length;
            E oldValue = get(elements, index);
            int numMoved = len - index - 1;
            if (numMoved == 0)
                setArray(Arrays.copyOf(elements, len - 1));
            else {
                Object[] newElements = new Object[len - 1];
                System.arraycopy(elements, 0, newElements, 0, index);
                System.arraycopy(elements, index + 1, newElements, index,
                                 numMoved);
                setArray(newElements);
            }
            return oldValue;
        }
    }
    
    final void setArray(Object[] a) {
        elements = a;
    }
    

    从代码中可以看到:iterator返回的是COWIterator,COWIterator实际上遍历的是,当前的elements。而在每次都会将旧的元素拷贝到一个新的数组中然后再进行操作.

    一个例子

    CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();
    list.add("A");
    list.add("B");
    list.add("C");
    for (String str : list) {
        System.out.print(str + "\r\n");
    }
    

    输出结果为:

    A

    B

    C

    相关文章

      网友评论

          本文标题:Java fail-fast 和 fail-safe机制

          本文链接:https://www.haomeiwen.com/subject/jdjmpxtx.html