Wrayの知识库 Wrayの知识库
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
  • Java章节编写规范
  • Java基础

  • Java集合

  • Java并发

    • Java并发概述
    • 线程与进程
    • Thread类与线程生命周期
    • 线程创建与任务模型
    • 线程安全
    • synchronized关键字
    • volatile关键字
    • Java内存模型(JMM)
    • 线程间通信
    • 线程池
    • 并发工具类
    • 原子操作类Atomic
    • 并发锁
    • 并发容器
    • ConcurrentHashMap
    • BlockingQueue
    • CopyOnWriteArrayList
      • 1. 写时复制模型
      • 2. 示例
      • 3. 迭代快照
      • 4. 适用场景
      • 5. addIfAbsent
      • 6. 与 synchronizedList 对比
      • 7. 内存成本
      • 专家实践与边界
      • Tips 快问快答
    • ThreadLocal
    • Fork/Join框架
    • ScheduledThreadPoolExecutor
    • CompletableFuture
    • 虚拟线程
    • 死锁活锁与线程问题排查
    • 并发编程最佳实践
  • Java IO

  • JVM

  • Java
  • Java并发
Wray
2026-06-24
目录

CopyOnWriteArrayList

CopyOnWriteArrayList 是线程安全的 List,核心思想是写时复制。读操作不加锁,写操作复制底层数组并替换引用。

# 1. 写时复制模型

读线程
  │
  ▼
读取当前数组快照

写线程
  │
  ▼
加锁 -> 复制数组 -> 修改新数组 -> 替换数组引用

读写互不阻塞,读操作非常快,写操作成本高。

# 2. 示例

CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
list.add("A");
list.add("B");

for (String value : list) {
    System.out.println(value);
}

适合读多写少的数据。

# 3. 迭代快照

迭代器基于创建时的数组快照。

Iterator<String> iterator = list.iterator();
list.add("C");

while (iterator.hasNext()) {
    System.out.println(iterator.next()); // 看不到 C
}

模型:

iterator -> old array [A, B]
list     -> new array [A, B, C]

因此遍历不会抛 ConcurrentModificationException,但也看不到之后的修改。

# 4. 适用场景

适合:

  • 监听器列表。
  • 配置快照。
  • 黑白名单。
  • 读远多于写。
  • 列表规模不大。

不适合:

  • 高频写入。
  • 大列表。
  • 强实时一致读取。

# 5. addIfAbsent

list.addIfAbsent("A");

如果元素不存在才添加。适合监听器注册等场景。

但它仍要遍历判断和写时复制,数据量大时成本不低。

# 6. 与 synchronizedList 对比

对比项 CopyOnWriteArrayList synchronizedList
读操作 无锁快照读 加锁
写操作 复制数组,成本高 加锁修改
迭代 快照,不 fail-fast 遍历需手动同步
适合 读多写少 读写都不太高的简单同步

# 7. 内存成本

写入时会同时存在旧数组和新数组:

old array [A, B, C]
new array [A, B, C, D]

大列表频繁写入会带来内存和 GC 压力。

# 专家实践与边界

CopyOnWriteArrayList 的核心思想是读不加锁,写时复制新数组。它牺牲写入性能和内存,换取读路径的简单稳定。

读操作
  └─ 直接读取当前数组快照

写操作
  ├─ 加锁
  ├─ 复制旧数组
  ├─ 修改新数组
  └─ 替换引用
场景 是否适合 原因
配置监听器列表 适合 读多写少
黑白名单小集合 适合 迭代频繁,修改少
高频写入列表 不适合 每次写复制数组
大集合 不适合 内存复制成本高
强实时一致遍历 谨慎 迭代器是快照

它非常适合“读远多于写且集合不大”的场景。看到高频 add/remove,应该优先考虑其他并发结构或读写锁方案。

# Tips 快问快答

Q:CopyOnWriteArrayList 适合什么场景? A:读多写少、列表不大的场景。

Q:写操作为什么慢? A:每次写都复制底层数组。

Q:迭代时能看到之后新增元素吗? A:看不到,迭代器基于创建时快照。

Q:会抛 ConcurrentModificationException 吗? A:通常不会。

Q:它适合高频写入吗? A:不适合,写入和 GC 成本很高。

Q:读取需要加锁吗? A:不需要,读当前数组引用。

Q:元素对象本身线程安全吗? A:不一定。列表结构安全不代表元素内部状态安全。

Q:大列表适合用它吗? A:通常不适合,复制成本太高。

上次更新: 2026/06/25, 14:19:18
BlockingQueue
ThreadLocal

← BlockingQueue ThreadLocal→

Copyright © 2023-2026 Wray | 鄂ICP备2024050235号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式