java中CopyOnWriteArrayList是什么
技术百科
冷漠man
发布时间:2025-12-20
浏览: 次 CopyOnWriteArrayList是读多写少场景下的线程安全集合,写操作复制整个数组,读操作无锁直接访问;2. 适合监听器列表、配置缓存等低频修改场景,不适用高频写或强一致需求;3. 相比ArrayList非线程安全,Vector和synchronizedList读写全加锁低吞吐,它读高效但可能读到旧数据快照。
CopyOnWriteArrayList 是 Java 并发包(java.util.concurrent)中一个线程安全的动态数组实现,它的核心特点是:**写操作(add、set、remove 等)会复制整个底层数组,读操作则直接在原数组上进行,不加锁。**
为什么叫 “Copy-On-Write”?
这个名字直译是“写时复制”。它的工作机制很简单:
- 每次执行修改操作(比如
add()、remove()、set())时,不是直接修改原数组,而是先创建一个新数组,把原数组内容复制过去,
再在新数组上做修改,最后用新数组原子性地替换掉旧数组。 - 所有读操作(如
get()、iterator()、size())全程不加锁,也不复制,直接访问当前引用的数组——哪怕这个数组正在被其他线程更新。
适合什么场景?
它最适合读多写少且对实时一致性要求不高的并发场景,比如:
- 监听器列表(Observer 模式):大量线程频繁遍历注册的监听器,但新增/移除监听器的操作很少。
- 配置项缓存、白名单、状态标记集合等:读取非常频繁,变更极少。
⚠️ 注意:它不适合写频繁或对数据强一致性敏感的场景。因为写操作开销大(复制整个数组),而且读操作看到的可能是“过期快照”——例如迭代过程中另一个线程删除了元素,迭代器也不会抛 ConcurrentModificationException,也不会反映这次删除。
和 ArrayList / Vector / Collections.synchronizedList 的区别
• ArrayList:非线程安全,读写都不加锁,多线程下可能出错。
• Vector / synchronizedList:读写都加同一把锁,串行化,吞吐量低,但能保证强一致性。
• CopyOnWriteArrayList:读完全无锁、高性能;写需复制+加锁(只锁写过程),但读到的数据可能滞后。
一个小例子帮你理解“读到旧数据”
假设 list 初始为 [A, B],线程 T1 正在遍历:
for (String s : list) { ... } // 此时拿到的是 [A, B] 的快照
与此同时,线程 T2 执行 list.remove("B") —— 它会复制出新数组 [A] 并替换。但 T1 的 for-each 仍在原数组 [A, B] 上运行,所以仍会遍历到 B,不会出错,也不会感知到已被删除。
基本上就这些。它不是万能的线程安全替代品,而是一个有明确适用边界的优化工具。
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- LINUX如何删除用户和用户组_Linux use
- Win11怎么关闭贴靠布局_Win11禁用窗口最大
- c++中如何使用虚函数实现多态_c++多态性实现原
- Win11怎么设置屏保_Windows 11屏幕保
- Win11怎么连接蓝牙耳机_Win11蓝牙设备配对
- VSC怎么在PHP中调试MySQL_数据库交互排查
- windows 10专注助手怎么关闭_window
- c++怎么实现高并发下的无锁队列_c++ std:
- Win11相机打不开提示错误怎么修_相机权限开启与
- MAC的“接续互通”功能无法使用怎么办_MAC检查
- php转mp4怎么保留字幕_php处理带字幕视频转
- php8.4匿名类怎么用_php8.4匿名类创建与
- c++中的可变参数模板(variadic temp
- Win11怎么开启自动HDR画质_Windows1
- php中::能访问全局变量吗_全局作用域与类作用域
- Windows如何查看和管理已安装的字体?(字体文
- 如何使用Golang理解结构体指针方法接收者_Go
- Python集合操作技巧_高效去重解析【教程】
- Win11键盘快捷键大全_Windows 11常用
- VSC怎么创建PHP项目_从零开始搭建项目的步骤【
- Mac怎么安装软件_Mac安装dmg与pkg文件的
- Windows怎样拦截WPS弹窗广告_Window
- 短链接怎么用php还原_从基础原理到代码实现教学【
- C++中引用和指针有什么区别?(代码说明)
- 如何使用正则表达式批量替换重复的 *- 模式为固定
- PHP主流架构如何做单元测试_工具与流程【详解】
- php删除数据怎么清空表_truncate与del
- Win11蓝牙开关不见了怎么办_Win11蓝牙驱动
- Mac如何备份到iCloud_Mac桌面与文稿文件
- Windows10系统怎么查看显卡驱动_Win10
- Win11怎么更改电脑密码_Windows 11修
- Win11怎么设置多显示器任务栏 Win11扩展任
- Windows 11登录时提示“用户配置文件服务登
- Win10怎样安装Word样式库_Win10安装W
- Mac如何查看电池健康百分比_Mac系统信息电源检
- 如何使用Golang管理模块版本_Golanggo
- Win11如何设置开机自动联网 Win11宽带连接
- Python模块的__name__属性如何由导入方
- Mac电脑如何恢复出厂设置_Mac抹掉数据并重装系
- PHP的Workerman对架构扩展有啥帮助_应用
- Win11怎么设置闹钟_Windows 11时钟应
- Win11怎么关闭系统推荐内容_Windows11
- c# 服务器GC和工作站GC的区别和设置
- Windows任务计划服务异常原因_任务调度失败的
- 如何在Golang中处理URL参数_Golang
- Win11右键反应慢怎么办 Win11优化右键菜单
- PHP主流架构怎么部署到Docker_容器化流程【
- VSC怎么配置PHP的Xdebug_远程调试设置步
- Mac如何使用听写功能_Mac语音输入打字【效率技
- Linux怎么设置磁盘配额_Linux系统Quot

再在新数组上做修改,最后用新数组原子性地替换掉旧数组。
QQ客服