news 2026/6/10 0:52:12

Java线程安全利器:CopyOnWriteArraySet详解

作者头像

张小明

前端开发工程师

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

一、一句话理解

CopyOnWriteArraySet是一个线程安全的、基于“写时复制”策略实现的 Set,内部使用CopyOnWriteArrayList存储元素,因此具备与之相同的并发特性:读操作无锁高效,写操作昂贵但安全。


二、核心设计原理

1.底层结构

privatefinalCopyOnWriteArrayList<E>al;
  • 所有操作都委托给内部的CopyOnWriteArrayList
  • 因为List允许重复,而Set不允许,所以:
    • 添加元素时调用al.addIfAbsent(e)(确保唯一性)
    • 批量添加调用al.addAllAbsent(c)

✅ 这样既复用了CopyOnWriteArrayList的线程安全机制,又通过“仅添加不存在元素”实现了 Set 的语义。


2.关键特性(继承自 COW 思想)

特性说明
线程安全所有修改操作加锁,读操作无锁(依赖 volatile 数组快照)
写操作昂贵每次add/remove都可能复制整个底层数组(O(n) 时间 + 内存)
迭代器快照调用iterator()时捕获当前数组状态,遍历时不受其他线程修改影响
不支持Iterator.remove()UnsupportedOperationException
允许 null 元素CopyOnWriteArrayList一致
元素顺序按插入顺序(因为底层是 List)

3.构造函数的优化

publicCopyOnWriteArraySet(Collection<?extendsE>c){if(c.getClass()==CopyOnWriteArraySet.class){// 如果传入的是另一个 CopyOnWriteArraySet,直接复制其内部 listal=newCopyOnWriteArrayList<E>(cc.al);}else{// 否则逐个去重添加(使用 addAllAbsent)al=newCopyOnWriteArrayList<E>();al.addAllAbsent(c);}}
  • 避免重复去重:如果源集合已经是CopyOnWriteArraySet,说明它本身无重复,可直接拷贝底层数组。
  • 否则安全去重:通过addAllAbsent确保新集合中无重复。

4.equals()方法的特殊实现

publicbooleanequals(Objecto){// ...// 使用 O(n²) 算法比较两个集合是否相等// 因为假设集合很小(COW 适用场景),所以可以接受}
  • 为什么不用HashSet那种 O(n) 的方式?
    • 因为CopyOnWriteArraySet不提供哈希表结构,只能通过遍历比较。
    • 作者明确注释:“This algorithm is only appropriate for small sets”
  • 逻辑:对目标集合每个元素,在本集合中找一个未匹配过的相等元素,全部匹配且数量一致才算相等。

5.Spliterator 支持(Java 8+)

publicSpliterator<E>spliterator(){returnSpliterators.spliterator(al.getArray(),Spliterator.IMMUTABLE|Spliterator.DISTINCT);}
  • IMMUTABLE:遍历时底层数组不会变(快照)
  • DISTINCT:Set 天然无重复,告诉流框架可以做优化
  • 适用于并行流(parallel stream),但注意:由于是快照,看不到后续修改

三、适用场景(和CopyOnWriteArrayList一致)

读多写少
集合规模小(通常几十个元素以内)
需要在遍历时避免ConcurrentModificationException
不能或不方便在遍历时加锁

典型用例:

  • 事件监听器集合(如 GUI 回调、消息订阅)
  • 白名单/黑名单配置(偶尔更新,频繁检查)
  • 状态观察者列表
// 示例:注册回调处理器privatefinalCopyOnWriteArraySet<Callback>callbacks=newCopyOnWriteArraySet<>();publicvoidregister(Callbackcb){callbacks.add(cb);}publicvoidnotifyAll(){// 安全遍历,即使其他线程正在注册/注销for(Callbackcb:callbacks){cb.onEvent();}}

四、与ConcurrentHashMap.newKeySet()Collections.synchronizedSet(new HashSet())对比

方案读性能写性能内存是否有序适用场景
CopyOnWriteArraySet⭐⭐⭐ 极高(无锁)⭐ 极低(复制数组)高(写时双倍)✅ 插入顺序小集合、高频读、低频写
Collections.synchronizedSet(HashSet)⭐ 需加锁⭐⭐ 中等❌ 无序通用同步,但遍历需手动同步
ConcurrentHashMap.newKeySet()⭐⭐ 高(分段锁/CAS)⭐⭐⭐ 高❌ 无序高并发读写、大集合

💡 如果你不需要顺序,且写操作较频繁,ConcurrentHashMap.newKeySet()通常是更好的选择


五、注意事项

  1. 不要用于大数据量:写操作复制整个数组,GC 压力大。
  2. add()返回值有意义:只有当元素原本不存在时才返回true
  3. 组合操作非原子:例如if (!set.contains(x)) set.add(x)不是线程安全的(虽然add本身去重,但中间可能被其他线程插入)。
  4. 迭代器是“过期”的:它反映的是创建时刻的状态,不是实时视图。

六、总结

CopyOnWriteArraySetCopyOnWriteArrayList的 Set 封装版,通过委托 + 去重逻辑,实现了线程安全的无重复集合。它的设计哲学是:

“牺牲写性能,换取极致的读性能和遍历安全性”

在合适的场景下(小、读多、写少),它是优雅且高效的解决方案;但在高写频或大数据场景下,应考虑其他并发 Set 实现。


如果你正在处理回调注册、监听器管理、配置项缓存等场景,CopyOnWriteArraySet很可能就是你要找的工具。

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

【VTK手册029】 VTK管线中Modified() 和Update()的底层逻辑解析

【VTK手册029】 VTK管线中Modified() 和Update()的底层逻辑解析 0. 前言&#xff1a;为何必须掌握 VTK 管线逻辑&#xff1f; 在医学图像算法开发中&#xff0c;性能优化与数据一致性是核心诉求。VTK&#xff08;Visualization Toolkit&#xff09;是基于数据驱动&#xff08;D…

作者头像 李华
网站建设 2026/6/9 13:34:30

智能游戏管家:用自动化脚本重新定义碧蓝航线体验

智能游戏管家&#xff1a;用自动化脚本重新定义碧蓝航线体验 【免费下载链接】AzurLaneAutoScript Azur Lane bot (CN/EN/JP/TW) 碧蓝航线脚本 | 无缝委托科研&#xff0c;全自动大世界 项目地址: https://gitcode.com/gh_mirrors/az/AzurLaneAutoScript 你是否曾经想过…

作者头像 李华
网站建设 2026/6/6 11:30:39

构建高效可追溯的测试资产治理体系

一、测试资产管理为何需要版本控制与配置管理&#xff1f;在敏捷与DevOps成为主流的今天&#xff0c;软件迭代速度急剧加快&#xff0c;测试活动也随之变得高频且复杂。测试团队在日常工作中产出并依赖大量资产&#xff0c;如&#xff1a;测试设计资产&#xff1a;测试计划、测…

作者头像 李华
网站建设 2026/6/6 4:58:05

超星网课助手终极使用指南:一键完成课程任务与资源下载

超星网课助手终极使用指南&#xff1a;一键完成课程任务与资源下载 【免费下载链接】chaoxing_tool 超星网课助手&#xff0c;拥有 一键完成超星中的任务点/刷取课程学习次数/下载课程资源 等功能。基于python语言 项目地址: https://gitcode.com/gh_mirrors/ch/chaoxing_too…

作者头像 李华
网站建设 2026/6/9 15:45:43

B站视频智能转文字神器:3步实现高效内容自动化提取

还在为B站视频中的精彩内容无法快速记录而烦恼吗&#xff1f;Bili2text作为一款开源智能工具&#xff0c;只需输入视频链接&#xff0c;就能将视频内容一键转换为完整文字稿&#xff0c;让知识获取变得前所未有的简单高效&#xff01; 【免费下载链接】bili2text Bilibili视频转…

作者头像 李华
网站建设 2026/6/9 9:49:44

6种高效策略完全突破付费墙:从新手到专家的完整指南

6种高效策略完全突破付费墙&#xff1a;从新手到专家的完整指南 【免费下载链接】bypass-paywalls-chrome-clean 项目地址: https://gitcode.com/GitHub_Trending/by/bypass-paywalls-chrome-clean 在信息爆炸的数字时代&#xff0c;你是否经常遇到这样的情况&#xff…

作者头像 李华