fail-fast 机制

简介: 大家好,我是指北君。PS:最近又赶上跳槽的高峰期,我连日加班好多天,终于整理好了,16000+ 道,295多份,多份面试题大全,我会持续更新中,马上就会整理更多!【文末有领取方式】

我的朋友小 B 今天去面试。面试结果有些惨淡。

面试官:能说说 fail-fast 是什么吗?

小 B:就是在多线程的时候,修改集合时引起 ConcurrentModificationException 异常的一种机制。

面试官:那么在单线程中,会出现吗?

小 B:不会出现。

面试官:你回去吧。


fail-fast 是什么


引用百度百科的数据:

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

多线程?并发修改?才会引起 fail-fast 机制保护程序?小 B 觉得这个答案没有说全,面试官说了单线程也会引起 fail-fast 机制。那么关于单线程是否会引起 fail-fast 机制,百度百科说的对还是面试官说的对,写一个 demo 就清楚了。

60.png

从下图的运行结果来看,list 已经完成了对 [赵六] 的 remove,说明并不是 remove 引发的问题,仔细查看异常原因:是在 ArrayList 的内部 Itr.checkForComodification() 方法出现的 ConcurrentModificationException 异常。小 B 感概了一句:网上资料不可尽信,动手实战才能出真知。


61.jpg


原理

将异常定位到报错的 ArrayList.java:911 行。

62.png


可以看到这个方法 checkForComodification 对 modCount 和 expectedModCount 进行了比较,如果不相同就抛出异常。modCount 和 expectedModCount 分别又是什么呢?remove 方法中不是修改了 modCount 就是修改了 expectedModCount。

modCount 被定义在 ArrayList 的父类 AbstractList 中,每一次调用 Add、Remove、Clear 等方法 modCount 就被 +1,可以说明这个变量的作用就是记录了 ArrayList 实际被修改的次数。

ArrayList 的 foreach 方法是用迭代器 Iterator 实现的,Iterator 在 ArrayList 中有一个实现类:Itr,它的成员变量 expectedModCount 在初始化的时候被赋值了 modCount。所以当 ArrayList 调用 remove 删除元素时,modCount 被 +1,此时不等于 expectedModCount,在 foreach 试图将局部变量 s 交接给下一个元素的时候,就出现了 ConcurrentModificationException 异常。

63.jpg



避免


经过分析,ConcurrentModificationException 是由于 modCount 和 expectedModCount 不一样导致的。

那么如何避免在循环的时候 add、remove 元素不抛出异常呢?


for 循环

使用普通的 for 循环,这样就可以不经过 Itr 内部类了

64.png


示例结果是 [张三, 李四, 赵六] 没有出现异常。但是移除元素后面的索引已经被改变了。

迭代器 Iterator

直接使用迭代器 Iterator 中的方法,在它的remove 方法中显示的将 expectedModCount 赋值成 modCount。

65.png


定义一个迭代器局部变量,使用 hasNext() 方法控制 while 循环。

66.png


CopyOnWriteArrayList

CopyOnWriteArrayList 是 java 并发包 java.util.concurrent 下面的类。它在操作 add、remove 元素时,先将原来的元素数组拷贝一份成为新的数组,在新数组上面做元素操作,修改完成后,将 CopyOnWriteArrayList 中数组的引用指向了新数组。


67.png


总结


fail-fast 机制就是不允许程序员不管是在单线程还是多线程环境中遍历集合的时候顺便还操作集合里面的元素。

我是指北君,操千曲而后晓声,观千剑而后识器。感谢各位人才的:点赞、收藏和评论,我们下期更精彩!

面试大全包括:包括 Java 集合、JVM、多线程、并发编程、设计模式、SpringBoot、SpringCloud、Java、MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、MongoDB、Redis、MySQL、RabbitMQ、Kafka、Linux、Netty、Tomcat、Python、HTML、CSS、Vue、React、JavaScript、Android 大数据、阿里巴巴等大厂面试题等、等技术栈!

领取方式:扫描下方公众号【Java技术指北】回复【006】即可获取

68.jpg

相关文章
|
27天前
|
安全 Java 程序员
深入Java集合框架:解密List的Fail-Fast与Fail-Safe机制
本文介绍了 Java 中 List 的遍历和删除操作,重点讨论了快速失败(fail-fast)和安全失败(fail-safe)机制。通过普通 for 循环、迭代器和 foreach 循环的对比,详细解释了各种方法的优缺点及适用场景,特别是在多线程环境下的表现。最后推荐了适合高并发场景的 fail-safe 容器,如 CopyOnWriteArrayList 和 ConcurrentHashMap。
53 5
|
Java 容器
Iterator_fail-fast和Iterator_fail-safe~
Iterator_fail-fast和Iterator_fail-safe~
|
6月前
|
安全 Java 容器
浅谈从fail-fast机制到CopyOnWriteArrayList使用
浅谈从fail-fast机制到CopyOnWriteArrayList使用
52 0
|
Java
什么是fail-fast
什么是fail-fast
65 0
|
监控 安全
故事会【Fail-safe和Fail-fast】
故事会【Fail-safe和Fail-fast】
|
安全 Java 容器
什么是fail-fast和fail-safe?
本章讲解了什么是fail-fast和fail-safe,以及如何解决
116 0
|
Java
【Java】从源码分析fail-fast和fail-safe是如何产生的
【Java】从源码分析fail-fast和fail-safe是如何产生的
80 0
|
Java API
Java - Java集合中的快速失败Fail Fast 机制
Java - Java集合中的快速失败Fail Fast 机制
82 0
|
安全 Java
fail-safe 和 fail-fast 硬核解析,让你和面试官多聊十分钟!
简介 java.util 包下的 属于 fail-fast , 快速失败~ 😝 java.util.concurrent 包下的 属于 fail-safe ,安全失败~ 😝 简单来说 就是 fail-fast 在迭代时,如果发现 该集合数据 结构被改变 (modCount != expectedModCount),就会 抛出 ConcurrentModificationException 小伙伴们可以参考下 下面的代码简单实验一下~ 😋 fail-fast 实验代码 实验对象是 Hashtable,这里采用 jdk1.7 的写法 ~ 因为博主还在研究 下文
229 0