
CopyOnWriteArraySet 是 Java 中用于在多线程环境下安全操作集合的一种实现。它之所以能保证线程安全,核心机制在于其底层依赖了 CopyOnWriteArrayList。
基于写时复制(Copy-On-Write)机制
CopyOnWriteArraySet 并没有直接实现自己的线程安全逻辑,而是内部持有一个 CopyOnWriteArrayList 对象,并通过它来存储元素。所有对集合的修改操作(如 add、remove)都会触发“写时复制”机制:
- 每当有线程尝试修改集合时,系统会创建底层数组的一个新副本。
- 修改操作在新副本上进行,原数组保持不变。
- 修改完成后,原子地将内部引用指向新数组。
由于读操作不需要加锁,始终读取的是当前快照,而写操作彼此之间是互斥且独立作用于新副本,因此避免了读写冲突,也防止了并发修改异常(ConcurrentModificationException)。
利用内部集合去重保障 Set 特性
CopyOnWriteArraySet 借助 CopyOnWriteArrayList 存储数据,但 Set 要求元素唯一。其实现方式是在添加元素时,先检查是否已存在该元素:
立即学习“Java免费学习笔记(深入)”;
- 调用 add(E e) 方法时,会遍历当前数组判断元素是否已存在。
- 只有当元素不存在时,才会执行写时复制流程,添加新元素。
这一过程虽然在高并发下可能多个线程同时进入判断,但由于写操作是加锁并复制的,最终只会有一个写结果生效,从而保证了元素的唯一性。
读操作完全无锁,写操作互斥
该集合适用于读多写少的场景:
- 读操作(如 contains、迭代)不加锁,性能高,不会阻塞。
- 写操作(add、remove)使用可重入锁(ReentrantLock)互斥执行,确保同一时间只有一个线程能修改集合。
正因为写操作需要复制整个数组,所以频繁写入会导致性能下降和内存开销增大,但在读远大于写的并发场景中表现良好。
基本上就这些。CopyOnWriteArraySet 通过封装 CopyOnWriteArrayList,结合写时复制和加锁机制,在保证线程安全的同时维持了 Set 的语义,适合特定并发读多写少的使用场景。










