码迷,mamicode.com
首页 > 编程语言 > 详细

java基础之ArrayList 和Vector、CopyOnWriteArrayList

时间:2020-06-06 21:24:44      阅读:70      评论:0      收藏:0      [点我收藏+]

标签:transient   cto   源代码   之间   lazy   迭代   int   mod   col   

1.我们都知道ArrayList 是线程不安全的,不存在同步。

2.像Vector这种,add、remove方法都是原子操作,不会被打断,但也仅限于此,如果有个线程在遍历某个Vector、有个线程同时在add这个Vector,99%的情况下都会出现ConcurrentModificationException,也就是fail-fast机制

3.说到底CopyOnWriteArrayList 是最安全的,CopyOnWriteArrayList为什么能解决同步的问题呢?CopyOnWrite容器即写时复制的容器。通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。CopyOnWriteArrayList中add/remove等写方法是需要加锁的,目的是为了避免Copy出N个副本出来,导致并发写。但是。CopyOnWriteArrayList中的读方法是没有加锁的。

fail-fast机制 是在迭代的时候产生的,当多个线程同时对Arraylist 进行add时,就会引发fail-fast机制。

技术图片

 

 从上面的源代码我们可以看出,迭代器在调用next()、remove()方法时都是调用checkForComodification()方法,它检测modCount == expectedModCount ? 若不等则抛出ConcurrentModificationException 异常,从而产生fail-fast机制。到了这一步我们也知道了,想要弄清楚fail-fast机制,首先我们需要搞清楚modCount 和expectedModCount。

expectedModCount 是在IteratorTest中定义的:int expectedModCount = ArrayList.this.modCount;所以他的值是不可能会修改的,所以会变的就是modCount。modCount是在 AbstractList 中定义的,为全局变量:

protected transient int modCount = 0;

那么他什么时候因为什么原因而发生改变呢?请看ArrayList的源码:

技术图片

 

 从上面的源代码我们可以看出,只要是涉及了改变ArrayList元素的个数的方法都会导致modCount的改变。所以我们这里可以初步判断由于expectedModCount 与modCount的改变不同步,导致两者之间不等,从而产生fail-fast机制。

我想各位已经基本了解了fail-fast的机制,那么平常我们如何去规避这种情况呢?这里有两种解决方案:

方案一:在遍历过程中所有涉及到改变modCount值得地方全部加上synchronized或者直接使用Collections.synchronizedList(不推荐)

方案二:使用CopyOnWriteArrayList来替换ArrayList。

 

转自  :https://baijiahao.baidu.com/s?id=1638201147057831295&wfr=spider&for=pc

java基础之ArrayList 和Vector、CopyOnWriteArrayList

标签:transient   cto   源代码   之间   lazy   迭代   int   mod   col   

原文地址:https://www.cnblogs.com/ScarecrowAnBird/p/13056301.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!