fail-fast和fail-safe详解

一时失言乱红尘 2021-09-22 08:04 338阅读 0赞

简介

fail-fast(快速失败)是Java对java.util包下的所有集合类的是一种错误检测机制。

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

区别

java.util包下面的所有的集合类都是快速失败的,而java.util.concurrent包下面的所有的类都是安全失败的。fail-fast(快速失败)的迭代器会抛出ConcurrentModificationException异常,而因为安全失败是基于对底层集合做拷贝,所以,它不受源集合上修改的影响,安全失败的迭代器永远不会抛出这样的异常。

fail-fast触发方式

首先是触发场景,若触发了快速失败,其场景一定是多线程同事操作一个集合类。以ArrayList来说,通过查看源码得知:在ArrayList中的Iterator(继承父类AbstractList中的Iterator)中发现,当对ArrayList进行迭代时,当调用next()和remove()方法时,会去调用检查方法checkForComodification()去检查是否要抛出ConcurrentModificationException异常。

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


具体检查方法:在说具体方法前,先要理解两个变量modCount 和expectedModCount。expectedModCount 当迭代器创建时创建并且赋值为modCount ,并且expectedModCount 不可以被修改,而modCount 当ArrayList每被结构上修改一次modCount ++,随意只要判断expectedModCount 和modCount 两个变量是否一致即可决定是否抛出异常。


所谓结构被修改指的是,当对集合进行add(), remove() 或clear() 操作时,即改变集合的长度时(我是这么理解的-.-)就会改变集合的结构。在这里需要注意一点:当该变集合中元素的取值时,这不是改变集合的结构。


fail-fast解决方法

可以使用java.util.concurrent包中的集合类进行操作。如需要一个ArrayList时可以使用java.util.concurrent中对应的CopyOnWriteArrayList类进行操作。CopyOnWriteArrayList和ArrayList所实现有所不同,CopyOnWriteArrayList没有继承于AbstractList,它仅仅只是实现了List接口。

fail-safe

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

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

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

发表评论

表情:
评论列表 (有 0 条评论,338人围观)

还没有评论,来说两句吧...

相关阅读

    相关 TCPUDP详解

    什么是TCP和UDP,以及二者区别是什么? TCP的全称为传输控制协议。这种协议可以提供面向连接的、可靠的、点到点的通信。 UDP全称为用户数据报协议,它可以提供非连接

    相关 CookieSession详解

    前言:         会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Session。Cookie通过在客

    相关 SessionCookie详解

    Cookie(客户端,不是内置对象): Cookie是由服务端生成,再发送给客户端保存,其作用相当于本地缓存; 优点:提高访问服务端的效率 。缺点:安全性比较差;