CopyOnWriteArrayList源码学习

81 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

常用List

List特点:有序,元素可能重复 ​

数据结构

数组

数组结构特点:适合随机读,写入性能比链表差

  1. ArrayList,并发不安全,读写均不加锁
  2. Vector,并发安全,读写均加锁
  3. CopyOnWriteArrayList,并发安全,读不加锁,写加锁

链表

数组结构特点:适合顺序读,写入性能比数组高

  1. LinkedList,并发不安全,读写均未加锁

写add

public void add(int index, E element) {
    final ReentrantLock lock = this.lock;
    // 1. 加锁
    lock.lock();
    try {
        // 2. 获取数组快照
        Object[] elements = getArray();
        int len = elements.length;
        if (index > len || index < 0)
            throw new IndexOutOfBoundsException("Index: "+index+
                                                ", Size: "+len);
        Object[] newElements;
        int numMoved = len - index;
        // 3. 如果插入指定的索引为尾部,则直接将老数组复制至新数组,并长度加1,待填充要插入的数据
        if (numMoved == 0)
            newElements = Arrays.copyOf(elements, len + 1);
        else {
            // 4. 如果插入指定的索引非尾部,则直接将老数组复制至新数组,并将指定的索引位置空出来,待填充要插入的数据
            newElements = new Object[len + 1];
            System.arraycopy(elements, 0, newElements, 0, index);
            System.arraycopy(elements, index, newElements, index + 1,
                             numMoved);
        }
        // 5. 写入数据至新数组
        newElements[index] = element;
        // 6. 更新数组指针指向新复制出来的数组
        setArray(newElements);
    } finally {
        // 7. 释放锁
        lock.unlock();
    }
}

读get

/**
 * {@inheritDoc}
 *
 * @throws IndexOutOfBoundsException {@inheritDoc}
 */
public E get(int index) {
    // 1. 读取数组快照
    return get(getArray(), index);
}

@SuppressWarnings("unchecked")
private E get(Object[] a, int index) {
    // 2. 从数组快照中读取指定索引处的数据
    return (E) a[index];
}

总结

CopyOnWriteArrayList适合读多写少的场景,读取数据不加锁,性能高于Vector,且线程并发安全,但读取数据的实时性比Vector差。写入性能相对于Vector差一些 ​

CopyOnWriteArrayList由于其"读写分离"的思想,并发修改也不会抛出ConcurrentModificationException异常 主要缺点

  1. 内存成倍占用
  2. 写入数据与读取数据的实时性较差,由于每次都要先拷贝原数组数据再写入,实时性与数据量成反比

性能

排序均由高至低 随机读

  1. ArrayList,CopyOnWriteArrayList
  2. Vector
  3. LinkedList

顺序读

  1. ArrayList,CopyOnWriteArrayList,LinkedList
  2. Vector

  1. LinkedList
  2. ArrayList
  3. Vector
  4. CopyOnWriteArrayList