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

相关文章
|
机器学习/深度学习 存储 数据采集
数据分析案例-基于多元线性回归算法预测学生期末成绩
数据分析案例-基于多元线性回归算法预测学生期末成绩
2295 0
数据分析案例-基于多元线性回归算法预测学生期末成绩
|
监控 Cloud Native 安全
基于 API 网关践行 API First 开发实践
API First 开发模式的核心在于:以 API 为先,将其视为“头等公民”,在构建应用、服务及集成之前,应优先定义并设计 API 及其配套。API First 作为一种相对较新的开发模式,它已逐渐流行并获得业内的广泛认可。
854 174
|
11月前
|
域名解析 JSON API
【干货满满】如何处理requests库调用API接口时的异常情况
在调用 API 时,网络波动、服务器错误、参数异常等情况难以避免。本文提供一套系统化的异常处理方案,涵盖 requests 库常见异常类型、处理策略、实战代码与最佳实践,通过分类处理、重试机制与兜底策略,提升接口调用的稳定性与可靠性。
|
7月前
|
CDN
阿里云CDN收费标准:流量价格、带宽峰值计费及月结95带宽峰值计费说明
阿里云CDN收费包含基础费与增值费。基础费默认按流量计费,支持阶梯价及资源包抵扣;也可选按带宽峰值或月结95带宽计费。增值费如HTTPS、QUIC、WAF、实时日志等按使用收费,不使用不计费。2024年最新价格详见官方页面。
1098 2
|
JSON 监控 Java
日志与追踪的完美融合:OpenTelemetry MDC 实践指南
日志与追踪的完美融合:OpenTelemetry MDC 实践指南
1081 24
|
人工智能 Kubernetes 监控
Kubernetes 故障诊断 AI 助手
【10月更文挑战第6天】
1016 1
|
机器学习/深度学习 人工智能 边缘计算
AI驱动的开源治理——社会综合治理智慧化系统的技术突破
通过AI识别与智能监控精准捕捉不文明行为,生成证据链并分级预警,识别精度达98%;跨部门联动平台打破信息孤岛,实现多部门高效协作,事件处置时间缩短至5分钟;多场景适配的开源架构支持景区、校园等多样化需求,灵活部署边缘计算优化性能。试点成效显著,大幅提升治理效能。
491 14
|
前端开发 JavaScript Java
编程入门之前端和后端开发
前端开发就是开发网页上的内容展示与用户的交互,一部分后端开发工作就是开发数据访问服务,使前端可以通过后端服务对数据进行增删改查,也就是Crud,对前端用户的请求进行相应。
1330 8
|
机器学习/深度学习 存储 监控
基于YOLOv8深度学习的智能小麦害虫检测识别系统【python源码+Pyqt5界面+数据集+训练代码】目标检测、深度学习实战
基于YOLOv8深度学习的智能小麦害虫检测识别系统【python源码+Pyqt5界面+数据集+训练代码】目标检测、深度学习实战
|
Ubuntu 安全 搜索推荐
Linux Ubuntu 桌面环境概览
Ubuntu,在开源领域如同璀璨明星,以其卓越的桌面环境和用户体验赢得全球用户的心。采用优雅且功能丰富的GNOME桌面,Ubuntu界面简洁现代,提供直观易用的操作体验。无论是文件管理还是系统设置,图形界面让一切变得轻松。此外,高度可定制化特性让桌面成为个性展示的舞台,集成丰富应用满足多样化需求。背后强大的社区支持确保用户获得及时帮助,共享开源精神。
896 0