news 2026/9/30 3:46:42

Java线程安全利器:CopyOnWriteArrayList详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java线程安全利器:CopyOnWriteArrayList详解

一、一句话理解

CopyOnWriteArrayList是一个线程安全的 List,它通过“写时复制”(Copy-On-Write)策略实现并发控制:所有修改操作(add/set/remove 等)都会创建底层数组的一个全新副本,而读操作(get/iterator/size 等)直接访问当前快照,无需加锁。


二、核心设计思想

1.写时复制(Copy-On-Write)

  • 读操作无锁:因为底层数组是volatile的,读操作看到的是某个“瞬间快照”,天然线程安全。
  • 写操作加锁 + 复制:
    • 使用ReentrantLock保证同一时间只有一个写操作。
    • 修改时,不改动原数组,而是:
      1. 拷贝一份新数组(Arrays.copyOf)
      2. 在新数组上做修改
      3. 将array引用原子地指向新数组(volatile写)
publicbooleanadd(Ee){finalReentrantLocklock=this.lock;lock.lock();try{Object[]elements=getArray();// 旧数组Object[]newElements=Arrays.copyOf(elements,len+1);// 复制newElements[len]=e;// 修改副本setArray(newElements);// volatile 写,切换引用returntrue;}finally{lock.unlock();}}

2.弱一致性迭代器(Snapshot Iterator)

  • 调用iterator()时,会捕获当前array的引用(快照)。
  • 迭代过程中:
    • 不会抛出ConcurrentModificationException
    • 看不到之后的修改(因为用的是旧数组)
    • 不支持remove()/set()/add()→ 抛UnsupportedOperationException
publicIterator<E>iterator(){returnnewCOWIterator<E>(getArray(),0);// 传入当前 array 快照}

3.适用场景

✅读多写少(如监听器列表、配置项缓存)
✅遍历时不能加锁(避免死锁或性能瓶颈)
❌写操作频繁→ 每次复制数组开销大(O(n) 时间 + 内存)
❌实时性要求高→ 迭代器看不到最新修改


三、关键特性总结

特性说明
线程安全所有可变操作加锁,读操作无锁但可见性由volatile保证
内存一致性happens-before:写入前的操作对后续读取该元素的线程可见
允许 null 元素null被当作普通元素处理
fail-safe 迭代器基于快照,不抛ConcurrentModificationException
高写成本每次写都复制整个数组,适合小规模、低频修改
最终一致性读操作可能看到“过期”数据,但不会出错

四、与Vector/Collections.synchronizedList对比

CopyOnWriteArrayListVector/synchronizedList
读性能⭐⭐⭐ 极高(无锁)⭐ 需要获取锁
写性能⭐ 极低(复制整个数组)⭐⭐ 中等(只锁方法)
迭代行为快照,不阻塞写,不抛异常需手动同步,否则可能抛ConcurrentModificationException
内存占用高(写时双倍内存)低

五、使用示例

// 典型场景:事件监听器列表publicclassEventBus{privatefinalList<Listener>listeners=newCopyOnWriteArrayList<>();publicvoidaddListener(Listenerl){listeners.add(l);// 安全}publicvoidfireEvent(Evente){// 遍历时其他线程可安全增删监听器for(Listenerl:listeners){l.onEvent(e);}}}

六、注意事项

  1. 不要用于大数据量列表:写操作 O(n) 复制,GC 压力大。
  2. 不要依赖迭代器实时性:它反映的是调用iterator()时的状态。
  3. 组合操作非原子:如if (!list.contains(x)) list.add(x)不是原子的,需外部同步。

七、源码亮点

  • volatile Object[] array:保证数组引用的可见性。
  • ReentrantLock lock:细粒度控制写操作。
  • COWIterator:实现快照语义。
  • addIfAbsent/addAllAbsent:提供“去重添加”语义,内部也基于快照判断。

总结

CopyOnWriteArrayList是为高并发读、低频写场景量身定制的线程安全容器。它用空间换时间 + 最终一致性的思路,巧妙避免了读写冲突,是并发编程中“乐观锁”思想的经典体现。

如果你正在处理类似“观察者列表”、“白名单配置”等场景,它往往是比synchronizedList更优的选择。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/29 20:55:20

百度网盘下载优化工具:三分钟实现高效下载的实用方案

还在为百度网盘下载速度不理想而烦恼吗&#xff1f;这款实用的解析工具能有效提升你的下载体验&#xff0c;让文件传输更加顺畅。想象一下&#xff0c;原本需要较长时间的下载任务&#xff0c;现在能更快完成&#xff0c;这就是技术带来的便利&#xff01; 【免费下载链接】bai…

作者头像 李华
网站建设 2026/9/29 8:56:41

2025年华中科技大学计算机考研复试机试真题(附 AC 代码 + 解题思路)

2025年华中科技大学计算机考研复试机试真题 2025年华中科技大学计算机考研复试上机真题 历年华中科技大学计算机考研复试上机真题 历年华中科技大学计算机考研复试机试真题 更多学校题目开源地址&#xff1a;https://gitcode.com/verticallimit1/noobdream N 诺 DreamJudg…

作者头像 李华
网站建设 2026/9/29 16:00:36

NVIDIA显卡调优深度指南:专业级驱动优化的4大实战方案

NVIDIA显卡调优深度指南&#xff1a;专业级驱动优化的4大实战方案 【免费下载链接】nvidiaProfileInspector 项目地址: https://gitcode.com/gh_mirrors/nv/nvidiaProfileInspector 想要完全释放NVIDIA显卡的隐藏性能&#xff1f;NVIDIA Profile Inspector正是你需要的…

作者头像 李华
网站建设 2026/9/29 21:33:13

终极百度网盘下载加速方案:5个步骤实现全速下载

终极百度网盘下载加速方案&#xff1a;5个步骤实现全速下载 【免费下载链接】baidu-wangpan-parse 获取百度网盘分享文件的下载地址 项目地址: https://gitcode.com/gh_mirrors/ba/baidu-wangpan-parse 百度网盘直链解析技术为网络传输效率带来了革命性突破&#xff0c;…

作者头像 李华
网站建设 2026/9/29 12:19:23

【Java】【JVM】OOM 原因、定位与解决方案

JVM OOM 全景解析&#xff1a;原因、定位与实战解决方案 JVM OutOfMemoryError 是生产环境中最致命的故障之一&#xff0c;直接导致应用崩溃。系统掌握 OOM 的触发场景、定位工具和解决方案&#xff0c;是 Java 开发者的核心能力。一、OOM 常见原因分类&#xff08;9 大核心场景…

作者头像 李华
网站建设 2026/9/29 14:36:58

Unity游戏翻译工具:3步轻松实现海外游戏无障碍体验

Unity游戏翻译工具&#xff1a;3步轻松实现海外游戏无障碍体验 【免费下载链接】XUnity.AutoTranslator 项目地址: https://gitcode.com/gh_mirrors/xu/XUnity.AutoTranslator 还在为看不懂的日文游戏剧情而苦恼吗&#xff1f;想要畅玩海外优质Unity游戏却受限于语言障…

作者头像 李华