CopyOnWriteArrayList源码分析
特性
- 底层采用数组存储元素
- 线程安全
源码
查看一下关键的源码实现逻辑。
/** The lock protecting all mutators */
final transient ReentrantLock lock = new ReentrantLock();
/** The array, accessed only via getArray/setArray. */
private transient volatile Object[] array;
定义了一个lock进行同步操作,和一个存储数据的数组array。
这里我们只看一下add和get方法就能搞清楚他的实现原理。
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1); //创建一个长度比原来多出一个的新数组,然后将原有数据复制到新数组中
newElements[len] = e; //新元素放放新数组的最后一个位置
setArray(newElements); //用新数组替换原来的数组
return true;
} finally {
lock.unlock();
}
}
private E get(Object[] a, int index) {
return (E) a[index];
}
public E get(int index) {
return get(getArray(), index);
}
首先add方法是在同步代码块中的,他的思路是,创建一个更大的数组,将元素添加到新数组中,然后用新数组替换原有数组。get方法不需要同步机制,直接过去对应的数组元素即可。
总结
CopyOnWriteArrayList集合的实现机制决定了,他不会有扩容机制,因为每一次添加元素都会创建一个新的数组,然后替换原有数组,当然这也比较耗性能,但是查找操作没有同步限制,效率很高的。