CopyOnWriteArrayList
1. 前言
- 相当于线程安全的ArrayList
- 适用于:List 大小通常保持很小,只读操作远多于可变操作,需要在遍历期间防止线程间的冲突
- 可变操作(add()、set() 和 remove() 等)需要复制整个基础数组,所以开销很大
- 迭代器支持hasNext(), next()等不可变操作,但不支持可变 remove()等操作
- 使用迭代器进行遍历的速度很快,并且不会与其他线程发生冲突。在构造迭代器时,迭代器依赖于不变的数组快照。
2. 源码分析
2.1 数据结构
1 | public class CopyOnWriteArrayList<E> |
UML类图如下:
- CopyOnWriteArrayList包含了成员lock。每一个CopyOnWriteArrayList都和一个互斥锁lock绑定,通过lock,实现了对CopyOnWriteArrayList的互斥访问。 在“添加/修改/删除”数据时,会先“获取互斥锁”,再修改完毕之后,先将数据更新到“volatile数组”中,然后再“释放互斥锁”
- CopyOnWriteArrayList包含了成员array数组,这说明CopyOnWriteArrayList本质上通过数组实现的。通过 “volatile数组”(array)来保持数据。在“添加/修改/删除”数据时,都会新建一个数组,并将更新后的数据拷贝到新建的数组中,最后再将该数组赋值给“volatile数组”
2.2 核心方法
- 构造函数
1 | public CopyOnWriteArrayList() { |
构造函数通过setArray赋值:
1 | final Object[] getArray() { |
- add(int index, E element)
1 | //在指定位置插入元素 |
- get
1 | //返回第index个元素 |
- remove
1 | public E remove(int index) { |
- 迭代遍历
1 | public Iterator<E> iterator() { |
迭代通过COWIterator对象实现,COWIterator不支持remove(),set(),add()操作,非fail-fas机制
1 | static final class COWIterator<E> implements ListIterator<E> { |
- addIfAbsent
1 | public boolean addIfAbsent(E e) { |