Part1CopyOnWriteList简介
ArrayList是线程不安全的,于是JDK新增加了一个线程并发安全的List——CopyOnWriteList,中心思想就是copy-on-write
,简单来说是读写分离:读时共享、写时复制(原本的array)更新(且为独占式的加锁)
,而我们下面分析的源码具体实现也是这个思想的体现。
继承体系:

我们单独看一下CopyOnWriteList的主要属性和下面要主要分析的方法有哪些。从图中看出:
-
每个CopyOnWriteList对象里面有一个array数组来存放具体元素
-
使用ReentrantLock独占锁来保证只有写线程对array副本进行更新。
-
CopyOnWriteArrayList在遍历的使用不会抛出ConcurrentModificationException异常,并且遍历的时候就不用额外加锁
下面还是主要看CopyOnWriteList的实现
成员属性
//这个就是保证更新数组的时候只有一个线程能够获取lock,然后更新
final transient ReentrantLock lock = new ReentrantLock();
/*
使用volatile修饰的array,保证写线程更新array之后别的线程能够看到更新后的array.
但是并不能保证实时性:在数组副本上添加元素之后,还没有更新array指向新地址之前,别的读线程看到的还是旧的array
*/
private transient volatile Object[] array;
//获取数组,非private的,final修饰
final Object[] getArray() {
return array;
}
//设置数组
final void setArray(Object[] a) {
array = a;
}
构造方法
(1)无参构造,默认创建的是一个长度为0的数组
/*这里就是构造方法,创建一个新的长度为0的Object数组
然后调用setArray方法将其设置给CopyOnWriteList的成员变量array*/
public CopyOnWriteArrayList() {
setArray(new Object[0]);
}
(2)参数为Collection的构造方法
//按照集合的迭代器遍历返回的顺序,创建包含传入的collection集合的元素的列表
//如果传递的参数为null,会抛出异常
public CopyOnWriteArrayList(Collection<? extends E> c) {
Object[] elements; //一个elements数组
//这里是判断传递的是否就是一个CopyOnWriteArrayList集合
if (c.getClass() == CopyOnWriteArrayList.class)
//如果是,直接调用getArray方法,获得传入集合的array然后赋值给elements
elements = ((CopyOnWriteArrayList<?>)c).getArray();
else {
//先将传入的集合转变为数组形式
elements = c.toArray();
//c.toArray()可能不会正确地返回一个 Object[]数组,那么使用Arrays.copyOf()方法
if (elements.getClass() != Object[].class)
elements = Arrays.copyOf(elements, elements.length, Object[].class);
}
//直接调用setArray方法设置array属性
setArray(elements);
}
(3)创建一个包含给定数组副本的list
public CopyOnWriteArrayList(E[] toCopyIn) {
setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class));
}
上面介绍的是CopyOnWriteList的初始化,三个构造方法都比较易懂,后面还是主要看看几个主要方法的实现
添加元素
下面是add(E e)方法的实现 ,以及详细注释
public boolean add(E e) {
//获得独占锁
final ReentrantLock lock = this.lock;
//加锁
lock.lock();
try {
//获得list底层的数组array
Object[] elements = getArray();
//获得数组长度
int