CopyOnWriteArrayList的迭代器基于快照,add()添加的元素对当前迭代器完全不可见;迭代器只读,不支持remove/set/add;可见性以iterator()调用时刻为界,适合高并发读、低频写的场景。

在 CopyOnWriteArrayList 的 fail-safe 迭代过程中执行 add(),新添加的元素对当前迭代器**完全不可见**——这不是 bug,而是明确设计行为。
迭代器基于快照,不感知后续写操作
调用 iterator() 时,CopyOnWriteArrayList 会立即捕获当前底层数组的引用(即“快照”),后续所有 next() 都在这个固定数组上进行。即使其他线程或同一线程在迭代中途调用 add():
- 该
add()会加锁、复制原数组、扩容、插入新元素、原子更新内部数组引用; - 但老的快照数组不受影响,当前迭代器仍按原长度和内容继续遍历;
- 新增元素只存在于新数组中,只有下次调用
iterator()才能访问到。
当前迭代器无法修改,也不允许修改
CopyOnWriteArrayList 的迭代器是只读视图:
- 调用
iterator.remove()、iterator.set()或iterator.add()均抛出UnsupportedOperationException; - 这进一步确保了迭代过程的数据隔离性——既不能改快照,也不能干扰快照生命周期。
可见性边界清晰:以 iterator() 调用时刻为界
数据可见性严格遵循时间切片逻辑:
立即学习“Java免费学习笔记(深入)”;
- 迭代器看到的是构造那一刻的全部元素(包括当时已存在但尚未被遍历的);
- 它看不到任何发生在
iterator()返回之后的增删改; - 哪怕
add()和next()在毫秒级内交错执行,也绝无例外。
适用场景与注意事项
这种弱一致性模型适合对实时性要求不高、但需要高并发读取的场景:
- 事件监听器列表(如 Swing 或自定义 Observer)、配置白名单、缓存索引等;
- 若业务依赖“边遍历边收集新数据”,应避免在此迭代中调用
add(),改用临时集合暂存,遍历结束后批量合并; - 高频写操作会频繁触发数组复制,显著增加 GC 压力和 CPU 开销,需谨慎评估写入频率。


















