多线程(34)CopyOnWriteArrayList

CopyOnWriteArrayList 是 Java 中一个线程安全的 ArrayList 变体,属于 java.util.concurrent 包。它通过在所有修改操作(如 add, set 等)上执行显式复制来实现线程安全。这种设计适用于列表读操作的数量远远大于写操作的场景。

设计原理

CopyOnWriteArrayList 的基本思想是,每当我们要修改列表的时候(添加、删除、设置等),不直接在当前的数组上进行操作,而是先将当前数组复制一份,然后在这个副本上进行修改。修改完成后,再将原来的数组引用指向新数组。这样做的好处是可以避免修改时阻塞读操作,读操作可以安全地访问数组,不需要加锁,因为对它们来说,数组从不改变。

结构解析

CopyOnWriteArrayList 内部维护了一个 volatile 的数组用来存储数据。由于使用了 volatile 关键字,它保证了数组内容的可见性。以下是一个简化的 CopyOnWriteArrayList 类的源码结构(基于 Java 8+),展示了其基本实现:

java 复制代码
// 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 的简单示例:

java 复制代码
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 之前,需要确保它适合你的应用场景。

相关推荐
程序员cxuan26 分钟前
速度太快了!本地可以跑 DeepSeek-V4-Flash 了
人工智能·后端·程序员
阿祖zu2 小时前
芝士就是力量!开源私有化部署与 GitHub 双向同步的个人知识笔记 App
前端·后端·ios
不才不才不不才2 小时前
Spring 源码系列(16): doDispatch 全流程——一次请求的主干链路
java·后端·spring
IT_陈寒2 小时前
SpringBoot自动配置失效?这个隐藏配置坑了我一整晚
前端·人工智能·后端
搜狐技术产品小编20232 小时前
告别“黑盒”与误判:如何用“多智能体对抗辩论”重构内容安全审核系统
后端·多agent
DantyWei2 小时前
controller注册及调用时机
后端
edwarddamon3 小时前
Spring Cloud 配置热更新与 Bean 代理机制梳理
java·后端
码事漫谈3 小时前
我用 Seed Evolving 做了个 AI 小说写作工具
后端
Raas1003 小时前
MAIGateway,魔芋企业级AI网关的FinAPI成本竞争力设计
java·后端·网关·api网关·魔芋ai·finapi·mai gateway
计算机魔术师4 小时前
传统基础架构 - 微服务
大数据·后端·微服务·架构·开发工具·编程语言