2026/4/16 7:06:47
网站建设
项目流程
建设一个类似于猪八戒的网站需要,宝安建设网站公司,网络营销方式和消费者群体之间的关系,免费企业网站建设条件一、一句话理解CopyOnWriteArrayList 是一个线程安全的 List#xff0c;它通过“写时复制”#xff08;Copy-On-Write#xff09;策略实现并发控制#xff1a;所有修改操作#xff08;add/set/remove 等#xff09;都会创建底层数组的一个全新副本#xff0c;而读操作它通过“写时复制”Copy-On-Write策略实现并发控制所有修改操作add/set/remove 等都会创建底层数组的一个全新副本而读操作get/iterator/size 等直接访问当前快照无需加锁。二、核心设计思想1.写时复制Copy-On-Write读操作无锁因为底层数组是volatile的读操作看到的是某个“瞬间快照”天然线程安全。写操作加锁 复制使用ReentrantLock保证同一时间只有一个写操作。修改时不改动原数组而是拷贝一份新数组Arrays.copyOf在新数组上做修改将array引用原子地指向新数组volatile写publicbooleanadd(Ee){finalReentrantLocklockthis.lock;lock.lock();try{Object[]elementsgetArray();// 旧数组Object[]newElementsArrays.copyOf(elements,len1);// 复制newElements[len]e;// 修改副本setArray(newElements);// volatile 写切换引用returntrue;}finally{lock.unlock();}}2.弱一致性迭代器Snapshot Iterator调用iterator()时会捕获当前array的引用快照。迭代过程中不会抛出ConcurrentModificationException看不到之后的修改因为用的是旧数组不支持remove()/set()/add()→ 抛UnsupportedOperationExceptionpublicIteratorEiterator(){returnnewCOWIteratorE(getArray(),0);// 传入当前 array 快照}3.适用场景✅读多写少如监听器列表、配置项缓存✅遍历时不能加锁避免死锁或性能瓶颈❌写操作频繁→ 每次复制数组开销大O(n) 时间 内存❌实时性要求高→ 迭代器看不到最新修改三、关键特性总结特性说明线程安全所有可变操作加锁读操作无锁但可见性由volatile保证内存一致性happens-before写入前的操作对后续读取该元素的线程可见允许 null 元素null被当作普通元素处理fail-safe 迭代器基于快照不抛ConcurrentModificationException高写成本每次写都复制整个数组适合小规模、低频修改最终一致性读操作可能看到“过期”数据但不会出错四、与Vector/Collections.synchronizedList对比CopyOnWriteArrayListVector/synchronizedList读性能⭐⭐⭐ 极高无锁⭐ 需要获取锁写性能⭐ 极低复制整个数组⭐⭐ 中等只锁方法迭代行为快照不阻塞写不抛异常需手动同步否则可能抛ConcurrentModificationException内存占用高写时双倍内存低五、使用示例// 典型场景事件监听器列表publicclassEventBus{privatefinalListListenerlistenersnewCopyOnWriteArrayList();publicvoidaddListener(Listenerl){listeners.add(l);// 安全}publicvoidfireEvent(Evente){// 遍历时其他线程可安全增删监听器for(Listenerl:listeners){l.onEvent(e);}}}六、注意事项不要用于大数据量列表写操作 O(n) 复制GC 压力大。不要依赖迭代器实时性它反映的是调用iterator()时的状态。组合操作非原子如if (!list.contains(x)) list.add(x)不是原子的需外部同步。七、源码亮点volatile Object[] array保证数组引用的可见性。ReentrantLock lock细粒度控制写操作。COWIterator实现快照语义。addIfAbsent/addAllAbsent提供“去重添加”语义内部也基于快照判断。总结CopyOnWriteArrayList是为高并发读、低频写场景量身定制的线程安全容器。它用空间换时间 最终一致性的思路巧妙避免了读写冲突是并发编程中“乐观锁”思想的经典体现。如果你正在处理类似“观察者列表”、“白名单配置”等场景它往往是比synchronizedList更优的选择。