CopyOnWriteArrayList使用重入锁和写时复制(Copy On Write,COW)的读写分离策略,保证了线程安全。
存储结构
1 | /** The lock protecting all mutators */ |
实现原理
1.每当执行写操作(如add、set、remove等)时,都按照如下流程进行:
首先,加锁;
接着,将原数组array复制一份,得到新数组newElements(newElements.length = array.length + 1);
然后,在新数组newElements中执行写操作;
接下来,改变原数组,将新数组赋给它,即执行setArray(newElements);
最后,释放锁。
2.每当执行读操作(如get)时,总是在原数组中进行。
构造方法
1 | public CopyOnWriteArrayList() { |
添加元素
在尾部添加
1 | public boolean add(E e) { |
在指定位置添加
1 | public void add(int index, E element) { |
不存在时才添加
1 | public boolean addIfAbsent(E e) { |
indexOf方法用于查找某元素在[index, fence)中首次出现的位置。
1 | private static int indexOf(Object o, Object[] elements, |
根据数组的快照版本和给定的值,执行添加操作。
1 | private boolean addIfAbsent(E e, Object[] snapshot) { |
这里调用了eq方法,用于判断二者是否相等。
1 | private static boolean eq(Object o1, Object o2) { |
查询元素
所有的查询操作都在原数组中进行。由于get方法没有加锁,因此,可能会出现脏读(dirty read)。
1 | public E get(int index) { |
修改元素
1 | public E set(int index, E element) { |
删除元素
删除指定位置的元素
1 | public E remove(int index) { |
按值删除
删除数组中值为o(字母)的首个元素。
1 | public boolean remove(Object o) { |
根据数组的快照版本,以及待删除元素的值和索引,执行删除操作。
1 | private boolean remove(Object o, Object[] snapshot, int index) { |
迭代器
1 | public Iterator<E> iterator() { |
COWIterator使用的是原数组的快照,因此,COWIterator只支持访问操作,不允许在迭代时更新数组。
1 | static final class COWIterator<E> implements ListIterator<E> { |