返回
专项解读:CopyOnWriteArrayList底层机制
后端
2023-11-24 08:29:11
CopyOnWriteArrayList简介
CopyOnWriteArrayList是Java集合框架中的一种特殊的并发容器,它在读写分离的基础上实现了线程安全,读写操作不会互相阻塞,适用于读多写少的应用场景。
CopyOnWriteArrayList的底层原理是:每次修改操作都会创建一个新的内部数组,并将原数组的所有元素拷贝到新数组中,然后再对新数组进行修改。这样一来,读操作始终从原数组中获取数据,而写操作则在新的数组中进行,从而避免了读写冲突。
CopyOnWriteArrayList的底层原理
为了更深入地理解CopyOnWriteArrayList的底层原理,我们来看看它的源码。
public class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, Serializable {
private transient volatile Object[] array;
public CopyOnWriteArrayList() {
setArray(new Object[0]);
}
public CopyOnWriteArrayList(Collection<? extends E> c) {
Object[] elements;
if (c.getClass() == CopyOnWriteArrayList.class) {
elements = ((CopyOnWriteArrayList<?>) c).getArray();
} else {
elements = c.toArray();
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elements.getClass() != Object[].class)
elements = Arrays.copyOf(elements, elements.length, Object[].class);
}
setArray(elements);
}
public E get(int index) {
return getArray()[index];
}
public boolean add(E e) {
synchronized (this) {
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
}
}
private void setArray(Object[] a) {
array = a;
}
private Object[] getArray() {
return array;
}
}
从源码中可以看出,CopyOnWriteArrayList的底层是一个volatile修饰的数组array,它存储了所有的元素。
当调用get方法获取元素时,直接从array中获取,不会进行任何同步操作,因此get操作是线程安全的。
当调用add方法添加元素时,首先获取当前的array,然后创建一个新的数组,并将原数组的所有元素拷贝到新数组中,然后再将要添加的元素添加到新数组中,最后将array指向新数组。
由于add操作需要创建一个新的数组,因此是线程不安全的,需要进行同步操作。
CopyOnWriteArrayList的适用场景
CopyOnWriteArrayList适用于读多写少的应用场景,因为它的读操作是线程安全的,而写操作需要进行同步,因此如果写操作比较频繁,则会影响性能。
常见的适用场景包括:
- 线程池管理:线程池中维护着一个线程队列,当有任务提交时,会将任务添加到队列中,当线程池中空闲线程获取任务时,会从队列中获取一个任务并执行。
- 消息队列:消息队列中维护着一个消息队列,生产者线程将消息添加到队列中,消费者线程从队列中获取消息并处理。
- 并发缓存:并发缓存中维护着一个缓存,当有数据需要缓存时,会将数据添加到缓存中,当需要获取数据时,会从缓存中获取数据。
总结
CopyOnWriteArrayList是一种线程安全的并发容器,它在读写分离的基础上实现了线程安全,读写操作不会互相阻塞,适用于读多写少的应用场景。通过分析CopyOnWriteArrayList的源码,我们可以深入理解其底层工作原理和适用场景。