我的观点
fail-fast是什么就不多解释了,应该注意到的是(以ArrayList为例):modCount位于AbstractList中,

  1. protected transient int modCount = 0;

并无volatile修饰,因此当两线程是共用同一个cpu时才会抛出并发修改异常。比如:

线程1正在用迭代器来读,此时共用同一个cpu**的线程2来修改list,使得modCount++。由于共用同一个cpu,那么所修改的是**同一个缓存中的modCount,这样使得线程1下一次检查时发现与期望值不等,便会抛出异常

  1. final void checkForComodification() {
  2. if (modCount != expectedModCount)
  3. throw new ConcurrentModificationException();
  4. }

但是如果线程2用的是不同的cpu,而modCount又没有volatile修饰,那么线程2对modCount的修改不知道什么时候才会写回主存,也不知道什么时候线程1才会重新从主存中读取modCount。
因此出现并发修改也不一定会抛异常,而其实只要违反规则,单线程照样会抛出并发修改异常

  1. public static void main(String[] args) {
  2. ArrayList<Integer> list = new ArrayList<>();
  3. list.add(1);
  4. list.add(2);
  5. Iterator iterator=list.iterator();
  6. while(iterator.hasNext()){
  7. iterator.next();
  8. list.add(3);
  9. }
  10. }
  11. // Exception in thread "main" java.util.ConcurrentModificationException
  12. // at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
  13. // at java.util.ArrayList$Itr.next(ArrayList.java:859)
  14. // at github.com.AllenDuke.concurrentTest.future.FutureTest.main(FutureTest.java:29)

但是线程用哪个cpu执行任务是不可知的。

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

这句话会误让人以为,线程进去修改的时候+1,修改完就-1。但实际上modCount是只会递增的,至少在jdk1.8中没有发现modCount--或是--modCount。利用反射可以看出并不是退出方法就-1,如下:

  1. public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
  2. ArrayList<Integer> list = new ArrayList<>();
  3. Class c= AbstractList.class;
  4. Field modCountField = c.getDeclaredField("modCount");
  5. modCountField.setAccessible(true);
  6. for (int i = 0; i < 5; i++) {
  7. list.add(i);
  8. System.out.println(modCountField.get(list));
  9. }
  10. }
  11. // 1
  12. // 2
  13. // 3
  14. // 4
  15. //

或者这句话的意思是两个线程同时+1,这样的话,根本原因就和我的观点一致了。

解释为什么不能依赖fail-fast的更多相关文章

  1. 快速失败(fail—fast)和 安全失败(fail—safe)

    快速失败(fail-fast) 在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的结构进行了修改(增加.删除),则会抛出Concurrent Modification Exception. 原理 ...

  2. Fail Fast and Fail Safe Iterators in Java

    https://www.geeksforgeeks.org/fail-fast-fail-safe-iterators-java/ Fail Fast and Fail Safe Iterators ...

  3. Spring IOC源代码具体解释之容器依赖注入

    Spring IOC源代码具体解释之容器依赖注入 上一篇博客中介绍了IOC容器的初始化.通过源代码分析大致了解了IOC容器初始化的一些知识.先简单回想下上篇的内容 加载bean定义文件的过程.这个过程 ...

  4. fail fast和fail safe策略

    优先考虑出现异常的场景,当程序出现异常的时候,直接抛出异常,随后程序终止 import java.util.ArrayList; import java.util.Collections; impor ...

  5. 【问题】Could not locate PropertySource and the fail fast property is set, failing

    这是我遇到的问题 Could not locate PropertySource and the fail fast property is set, failing springcloud的其他服务 ...

  6. Java集合框架中的快速失败(fail—fast)机制

      fail-fast机制,即快速失败机制,是java集合框架中的一种错误检测机制.多线程下用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的内容进行了修改(增加.删除),则会抛出Concurre ...

  7. Java Gradle入门指南之依赖管理(添加依赖、仓库、版本冲突)

        开发任何软件,如何管理依赖是一道绕不过去的坎,软件开发过程中,我们往往会使用这样那样的第三方库,这个时候,一个好的依赖管理就显得尤为重要了.作为一个自动构建工作,Gradle对依赖管理有着很好 ...

  8. 简单解析依赖注入(控制反转)在Spring中的应用

    IoC——Inversion of Control  控制反转DI——Dependency Injection   依赖注入 大家都知道,依赖注入是Spring中非常重要的一种设计模式.可能很多初学者 ...

  9. AngularJS(15)-依赖注入

    AngularJS 依赖注入 什么是依赖注入 wiki 上的解释是:依赖注入(Dependency Injection,简称DI)是一种软件设计模式,在这种模式下,一个或更多的依赖(或服务)被注入(或 ...

随机推荐

  1. 记录一次mybatis genertor使用以及mapper扫描遇见的问题

    本记录适用初次接触mybatis,大神忽略... 整体上分两个部分: 1.使用mybatis genertor自动生成代码 2.mapper的扫描 1.使用mybatis genertor自动生成代码 ...

  2. Spring Boot2 系列教程 (四) | 集成 Swagger2 构建强大的 RESTful API 文档

    前言 快过年了,不知道你们啥时候放年假,忙不忙.反正我是挺闲的,所以有时间写 blog.今天给你们带来 SpringBoot 集成 Swagger2 的教程. 什么是 Swagger2 Swagger ...

  3. UIPickerView 模块示例demo

    本文出自APICloud官方论坛 UIPickerView 此模块封装了一个可以从屏幕底部向上弹出的 action 选择器(3D滚轮效果).开发者可自定义选择器的样式,包括:导航条颜色.高度,导航条上 ...

  4. Broken Necklace 坏掉的项链 USACO 模拟(易错)

    1004: 1.1.4Broken Necklace 坏掉的项链 时间限制: 1 Sec  内存限制: 128 MB提交: 11  解决: 9[提交] [状态] [讨论版] [命题人:外部导入] 题目 ...

  5. excel 转换成pdf 总结

    excl 转换成pdf 1.freespire   只能转换前三页 // 使用此组件 只能转换前3页 //需要引用 如下命名空间 //using Spire.Doc; //Document doc = ...

  6. RTC时间设置

    1.命令行输入date,查看系统时间. 2.命令行输入 date -s "2019-01-21 16:03:00" 修改系统时间. 3.命令行输入 hwclock -w 将修改后的 ...

  7. LeetCode 第七题--整数反转

    1. 题目 2.思路 1. 题目 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转. 示例 1: 输入: 123输出: 321 示例 2: 输入: -123输出: -321示例 ...

  8. SpringSecurity 默认表单登录页展示流程源码

    SpringSecurity 默认表单登录页展示流程源码 本篇主要讲解 SpringSecurity提供的默认表单登录页 它是如何展示的的流程, 涉及 1.FilterSecurityIntercep ...

  9. 每天翻译一点点: WPF Application Framework (WAF)

    ps:http://waf.codeplex.com/wikipage?title=Model-View-ViewModel%20Pattern&referringTitle=Document ...

  10. 个人第四次作业:Alpha项目测试

    个人第四次作业:Alpha项目测试 格式描述 详情 这个作业属于哪个课程 http://edu.cnblogs.com/campus/xnsy/GeographicInformationScience ...