目录
5.1 介绍
- 并发包中的并发 List 只有 CopyOnWriteArrayList。CopyOnWriteArrayList 是一个线程安全的 ArrayList,对其进行的修改操作都是在底层的一个复制的数组(快照)上进行的,也就是使用了写时复制策略,用来保证 list 的一致性,
- 但是获取—修改—写 入三步操作并不是原子性的,所以在增删改的过程中都使用了独占锁ReentrantLock,来保证在某个时间只有一个线程能对 list 数组进行修改。
- 但是在“获取指定位置元素”时没有加锁同步,所以 CopyOnWriteArrayList 提供了弱一致性的迭代器,从而保证在获取迭代器后,其他线程对 list 的修改是不可见的。
5.2 主要方法源码解析
初始化
//无参构造函数,在内部创建了一个大小为 0 的 Object 数组作为 //array 的初始值。 public CopyOnWriteArrayList() { setArray(new Object[0]); } //有参构造函数。 //创建一个list,其内部元素是入参toCopyIn的副本 public CopyOnWriteArrayList(E[] toCopyIn) { setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class)); } //入参为集合,将集合里面的元素复制到本list public CopyOnWriteArrayList(Collection<? extends E> c) { Object[] elements; if (c.getClass() == CopyOnWriteArrayList.class) elements = ((CopyOnWriteArrayList<?>)c).getArray(); else { elements = c.toArray(); if (elements.getClass() != Object[].class) elements = Arrays.copyOf(elements, elements.length, Object[].class); } setArray(elements); }
5.2.2 添加元素
CopyOnWriteArrayList 中用来添加元素的函数有 add(E e) , add(int index, E element),addIfAbsent(E e) 和 addAllAbsent(Collection<? extends E> c) 等。
public boolean add(E e) {
//获取独占锁(1)
final ReentrantLock lock = this.lock;
lock.lock();
try {
//(2)获取array
Object[] elements = getArray();
//(3)复制array到新数组,添加元素到新数组
int len = elements.leng