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

protected transient int modCount = 0;

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

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

final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}

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

public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
Iterator iterator=list.iterator();
while(iterator.hasNext()){
iterator.next();
list.add(3);
}
}
// Exception in thread "main" java.util.ConcurrentModificationException
// at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
// at java.util.ArrayList$Itr.next(ArrayList.java:859)
// 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,如下:

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

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

最新文章

  1. 使用bootstrap tooltip控件动态修改提示内容
  2. JavaScript之毒瘤
  3. JMS的可靠性
  4. 破解Mysql数据库密码
  5. 陈朱兴-js写法【案例】:
  6. Java public, private, protected and default
  7. 【protobuf进阶】通过.proto文件导出C#支持的.cs类文件
  8. JavaScript 客户端JavaScript之 Web浏览器的环境
  9. window环境下安装 pip 工具 【pip为Python的扩展管理工具】
  10. Python-老男孩-02_装饰器_面向对象_封装_继承_异常_接口_数据库
  11. Oracle11g静默安装
  12. python1数据链接总结
  13. 纯css3打造瀑布流布局
  14. [笔试题目]使用Stringbuffer无 参的构造函数创建 一个对象时,默认的初始容量是多少? 如果长度不够使用了,自动增长多少倍?
  15. MiniGUI 如何显示繁体字
  16. JavaScript-创建日志调试对象(面向对象实例)
  17. D. The Beatles
  18. jquery 全选、反选、获取值、背景行、隔行变色和鼠标略过变色变色全特效
  19. js实现复选框的全选、全不选和反选
  20. BZOJ1319Sgu261Discrete Roots——BSGS+exgcd+原根与指标+欧拉定理

热门文章

  1. JSP九大内置对象之session以及eclispe如何关联源码
  2. js最简单的编写地点
  3. es5和es6中查找数组中的元素
  4. STM32F429的特点
  5. DFS——深度优先搜索的一般格式
  6. FWT 入门
  7. python的logging模块使用方法
  8. 毒瘤养成记1: 如何卡hash
  9. Java入门 - 语言基础 - 01.Java简介
  10. Android studio 报错Error:Internal error: (java.lang.ClassNotFoundException) com.google.wireless.android.sdk.stats.IntellijIndexingStats$Index