真正支持安全并发修改的集合应从底层规避迭代与修改冲突,推荐copyonwritearraylist、concurrenthashmap及无锁结构,并提供原子复合操作接口。

不能靠捕获 ConcurrentModificationException 来实现“安全并发修改”,它只是检测到结构性修改的失败信号,不是设计契约。真正支持安全并发修改的自定义集合类,应从底层规避迭代与修改的冲突,而非事后抛异常再处理。
用线程安全的内部结构替代简单同步
避免在迭代时加锁整个集合(如 synchronized(this)),这会严重阻塞读操作。推荐组合使用:
- CopyOnWriteArrayList 思路:写操作复制底层数组,读操作始终访问快照——适合读多写少、迭代频繁的场景;
- ConcurrentHashMap 分段/桶级锁:写操作只锁对应哈希桶,迭代可与部分写操作并行;
- Lock-free 结构(如基于 CAS 的无锁队列):适用于特定场景,但实现复杂,需谨慎验证正确性。
分离迭代器与集合状态,支持弱一致性遍历
自定义迭代器不应依赖集合的实时 modCount,而应持有构造时的状态快照:
- 迭代器初始化时拷贝当前元素引用数组或节点链表头指针;
- 不检查
modCount,也不抛ConcurrentModificationException; - 明确文档说明:迭代结果反映某一时刻的近似快照,不保证强一致性(这是并发集合的合理取舍)。
提供明确的并发修改接口,而非隐藏风险
不要让 add()/remove() 在多线程下“看似能用”。应设计原子复合操作:
-
boolean addIfAbsent(E e):避免重复添加的竞争; -
E computeIfPresent(K key, BiFunction<k> remapping)</k>类接口(参考ConcurrentMap); - 对列表类,提供
replaceRange(int from, int to, Collection extends E> newElements)等批量原子操作。
禁用非线程安全的遗留模式
若集合类不打算兼容单线程快速路径,就主动破坏 modCount-expectedModCount 机制:
- 移除
modCount字段,或恒置为 0; - 迭代器构造时不记录预期值,
hasNext()/next()不做校验; - 在 JavaDoc 中清晰声明:“此类所有方法均为线程安全,迭代过程不会抛出
ConcurrentModificationException”。
安全并发修改的本质是放弃“实时一致性幻觉”,用快照、分段锁、CAS 或不可变性换取可用性。直接围绕 ConcurrentModificationException 做文章,往往意味着设计已偏离并发集合的正轨。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











