Java快速失败(fail-fast)和安全失败(fail-safe)区别

标签: java 安全
15人阅读 评论(0) 收藏 举报
分类:

一、快速失败

    在使用迭代器对集合对象进行遍历的时候,如果A线程对集合进行遍历,正好B线程对集合进行修改(增加、删除、修改)则A线程会抛出ConcurrentModificationException异常。

原理是:

    迭代器在遍历时直接访问集合中的内容,并且在遍历过程中使用一个 modCount 变量。集合在被遍历期间如果内容发生变化,就会改变modCount的值。每当迭代器使用hashNext()/next()遍历下一个元素之前,都会检测modCount变量是否为expectedmodCount值,是的话就返回遍历;否则抛出异常,终止遍历。

查看ArrayList源代码,在next方法执行的时候,会执行checkForComodification()方法

        @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];
        }
        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }

 注意:

    这里异常的抛出条件是检测到 modCount!=expectedmodCount 这个条件。如果集合发生变化时修改modCount值刚好又设置为了expectedmodCount值,则异常不会抛出。因此,不能依赖于这个异常是否抛出而进行并发操作的编程,这个异常只建议用于检测并发修改的bug。

场景:java.util包下的集合类都是快速失败的,不能在多线程下发生并发修改(迭代过程中被修改)

二、安全失败(fail-safe)

 采用安全失败机制的集合容器,在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容,在拷贝的集合上进行遍历。

 原理:

        由于迭代时是对原集合的拷贝进行遍历,所以在遍历过程中对原集合所作的修改并不能被迭代器检测到,所以不会触发Concurrent Modification Exception,例如CopyOnWriteArrayList。

缺点:

        基于拷贝内容的优点是避免了Concurrent Modification Exception,但同样地,迭代器并不能访问到修改后的内容,即:迭代器遍历的是开始遍历那一刻拿到的集合拷贝,在遍历期间原集合发生的修改迭代器是不知道的。

场景:

        java.util.concurrent包下的容器都是安全失败,可以在多线程下并发使用,并发修改。

快速失败和安全失败是对迭代器而言的。 快速失败:当在迭代一个集合的时候,如果有另外一个线程在修改这个集合,就会抛出ConcurrentModification异常,java.util下都是快速失败。 安全失败:在迭代时候会在集合二层做一个拷贝,所以在修改集合上层元素不会影响下层。在java.util.concurrent下都是安全失败


参考文章:https://blog.csdn.net/qq_31780525/article/details/77431970

查看评论

快速失败(fail-fast)和安全失败(fail-safe)

一:快速失败(fail—fast)           在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的内容进行了修改(增加、删除、修改),则会抛出Concurrent Modifica...
  • qq_31780525
  • qq_31780525
  • 2017-08-20 19:50:50
  • 324

java中fail-fast 和 fail-safe的区别

原文地址:http://javahungry.blogspot.com/2014/04/fail-fast-iterator-vs-fail-safe-iterator-difference-with...
  • ch717828
  • ch717828
  • 2015-07-15 13:39:58
  • 14064

java中的快速失败(fail-fast)与安全失败(fail-safe)

原文地址:http://javahungry.blogspot.com/2014/04/fail-fast-iterator-vs-fail-safe-iterator-difference-with...
  • qq_34771403
  • qq_34771403
  • 2017-11-19 12:20:40
  • 125

Java提高篇(三四)-----fail-fast机制

在JDK的Collection中我们时常会看到类似于这样的话:        例如,ArrayList:注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性...
  • chenssy
  • chenssy
  • 2014-07-26 22:40:44
  • 38043

Fail Fast与Fail Safe的区别

Fail FastFail Fast Iterator在遍历集合时,若该集合发生了结构性的改变,则将抛出 ConcurrentModification 异常。例如: Map premiu...
  • CanoeStream
  • CanoeStream
  • 2015-07-12 13:57:32
  • 1499

fail-fast 与 fail-safe 机制有什么区别

在我们详细讨论这两种机制的区别之前,首先得先了解并发修改。 1.什么是同步修改? 当一个或多个线程正在遍历一个集合Collection,此时另一个线程修改了这个集合的内容(添加,删除或者修...
  • u014692324
  • u014692324
  • 2017-11-19 21:08:43
  • 367

夜谈 Java中 Fail-fast 和 Fail-safe 的原理与使用

在我们详细讨论这两种机制的区别之前,首先得先了解并发修改。 1.什么是同步修改? 当一个或多个线程正在遍历一个集合Collection,此时另一个线程修改了这个集合的内容(添加,删除或者修改)。这...
  • bigtree_3721
  • bigtree_3721
  • 2017-03-27 23:40:03
  • 783

快速失败(fail-fast)和安全失败(fail-safe)的区别是什么?

一:快速失败(fail—fast)           在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的内容进行了修改(增加、删除、修改),则会抛出Concurrent Modifi...
  • weichi7549
  • weichi7549
  • 2018-03-23 19:45:38
  • 1

Java基础之——快速失败&安全失败(最全的总结)

Java基础之——快速失败&安全失败(最全的总结)
  • rexct392358928
  • rexct392358928
  • 2016-06-28 10:37:40
  • 8036

java中的fail-fast(快速失败)机制

引入 在前面介绍ArrayList的扩容问题时对于modCount的操作没有详细说明,该变量的操作在add,remove等操作中都会发生改变。那么该变量到底有什么作用呢? 简介 fail-fast 机...
  • zymx14
  • zymx14
  • 2017-10-30 16:38:06
  • 250
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 67万+
    积分: 8877
    排名: 2710
    博客专栏
    最新评论