本文主要是介绍多线程(34)CopyOnWriteArrayList,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
CopyOnWriteArrayList
是 Java 中一个线程安全的 ArrayList
变体,属于 java.util.concurrent
包。它通过在所有修改操作(如 add
, set
等)上执行显式复制来实现线程安全。这种设计适用于列表读操作的数量远远大于写操作的场景。
设计原理
CopyOnWriteArrayList
的基本思想是,每当我们要修改列表的时候(添加、删除、设置等),不直接在当前的数组上进行操作,而是先将当前数组复制一份,然后在这个副本上进行修改。修改完成后,再将原来的数组引用指向新数组。这样做的好处是可以避免修改时阻塞读操作,读操作可以安全地访问数组,不需要加锁,因为对它们来说,数组从不改变。
结构解析
CopyOnWriteArrayList
内部维护了一个 volatile
的数组用来存储数据。由于使用了 volatile
关键字,它保证了数组内容的可见性。以下是一个简化的 CopyOnWriteArrayList
类的源码结构(基于 Java 8+),展示了其基本实现:
// CopyOnWriteArrayList 源码片段(简化版本,基于 Java 8+)
class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, Serializable {// 确保可见性和禁止指令重排序private transient volatile Object[] array;// 获取底层数组的方法final Object[] getArray() {return array;}// 将数组设置为提供的数组final void setArray(Object[] a) {array = a;}// 添加元素的方法public boolean add(E e) {// 加锁以确保线程安全synchronized (this) {Object[] es = getArray();int len = es.length;// 复制出一个新数组es = Arrays.copyOf(es, len + 1);// 在新数组上操作es[len] = e;// 将原数组引用指向新数组setArray(es);return true;}}// 其他方法省略...
}
代码演示
下面是一个使用 CopyOnWriteArrayList
的简单示例:
import java.util.concurrent.CopyOnWriteArrayList;public class CopyOnWriteArrayListDemo {public static void main(String[] args) {CopyOnWriteArrayList<Integer> cowArrayList = new CopyOnWriteArrayList<>();// 示例:并发添加Thread thread1 = new Thread(() -> cowArrayList.add(1));Thread thread2 = new Thread(() -> cowArrayList.add(2));thread1.start();thread2.start();// 等待线程结束try {thread1.join();thread2.join();} catch (InterruptedException e) {Thread.currentThread().interrupt();}// 迭代并打印结果for (Integer i : cowArrayList) {System.out.println(i);}}
}
总结
CopyOnWriteArrayList
提供了一种避免读写冲突的方法,非常适合读多写少的并发场景。它的优势是在进行遍历操作时不需要锁定,因此可以提高遍历操作的并发性能。但是,由于每次修改都需要复制整个底层数组,所以写操作的成本相对较高,特别是对于数据量大的列表。在选择使用 CopyOnWriteArrayList
之前,需要确保它适合你的应用场景。
这篇关于多线程(34)CopyOnWriteArrayList的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!