java基础之ArrayList 和VectorCopyOnWriteArrayList

Posted 落叶归根

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java基础之ArrayList 和VectorCopyOnWriteArrayList相关的知识,希望对你有一定的参考价值。

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 和VectorCopyOnWriteArrayList的主要内容,如果未能解决你的问题,请参考以下文章

java基础之ArrayList 和VectorCopyOnWriteArrayList

剖析面试最常见问题之Java基础知识

java集合之ArrayList链表基础

Java基础系列--集合之ArrayList

java基础之ArrayList方法

java基础-arrayList