java并发容器CopyOnWriteArrayList实现原理及源码分析
发布时间 - 2026-01-11 01:14:16 点击率:次CopyOnWriteArrayList是Java并发包中提供的一个并发容器,它是个线程安全且读操作无锁的ArrayList,写操作则通过创建底层数组的新副本来实现,是一种读写分离的并发策略,我们也可以称这种容器为"写时复制器",Java并发包中类似的容器还有CopyOnWriteSet。本文会对CopyOnWriteArrayList的实现原理及源码进行分析。

实现原理
我们都知道,集合框架中的ArrayList是非线程安全的,Vector虽是线程安全的,但由于简单粗暴的锁同步机制,性能较差。而CopyOnWriteArrayList则提供了另一种不同的并发处理策略(当然是针对特定的并发场景)。
很多时候,我们的系统应对的都是读多写少的并发场景。CopyOnWriteArrayList容器允许并发读,读操作是无锁的,性能较高。至于写操作,比如向容器中添加一个元素,则首先将当前容器复制一份,然后在新副本上执行写操作,结束之后再将原容器的引用指向新容器。
优缺点分析
了解了CopyOnWriteArrayList的实现原理,分析它的优缺点及使用场景就很容易了。
优点:
读操作性能很高,因为无需任何同步措施,比较适用于读多写少的并发场景。Java的list在遍历时,若中途有别的线程对list容器进行修改,则会抛出ConcurrentModificationException异常。而CopyOnWriteArrayList由于其"读写分离"的思想,遍历和修改操作分别作用在不同的list容器,所以在使用迭代器进行遍历时候,也就不会抛出ConcurrentModificationException异常了
缺点:
缺点也很明显,一是内存占用问题,毕竟每次执行写操作都要将原容器拷贝一份,数据量大时,对内存压力较大,可能会引起频繁GC;二是无法保证实时性,Vector对于读写操作均加锁同步,可以保证读和写的强一致性。而CopyOnWriteArrayList由于其实现策略的原因,写和读分别作用在新老不同容器上,在写操作执行过程中,读不会阻塞但读取到的却是老容器的数据。
源码分析
基本原理了解了,CopyOnWriteArrayList的代码实现看起来就很容易理解了。
public boolean add(E e) {
//ReentrantLock加锁,保证线程安全
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
//拷贝原容器,长度为原容器长度加一
Object[] newElements = Arrays.copyOf(elements, len + 1);
//在新副本上执行添加操作
newElements[len] = e;
//将原容器引用指向新副本
setArray(newElements);
return true;
} finally {
//解锁
lock.unlock();
}
}
添加的逻辑很简单,先将原容器copy一份,然后在新副本上执行写操作,之后再切换引用。当然此过程是要加锁的。
删除操作
public E remove(int index) {
//加锁
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
E oldValue = get(elements, index);
int numMoved = len - index - 1;
if (numMoved == 0)
//如果要删除的是列表末端数据,拷贝前len-1个数据到新副本上,再切换引用
setArray(Arrays.copyOf(elements, len - 1));
else {
//否则,将除要删除元素之外的其他元素拷贝到新副本中,并切换引用
Object[] newElements = new Object[len - 1];
System.arraycopy(elements, 0, newElements, 0, index);
System.arraycopy(elements, index + 1, newElements, index,
numMoved);
setArray(newElements);
}
return oldValue;
} finally {
//解锁
lock.unlock();
}
}
删除操作同理,将除要删除元素之外的其他元素拷贝到新副本中,然后切换引用,将原容器引用指向新副本。同属写操作,需要加锁。
我们再来看看读操作,CopyOnWriteArrayList的读操作是不用加锁的,性能很高。
public E get(int index) {
return get(getArray(), index);
}
直接读取即可,无需加锁
private E get(Object[] a, int index) {
return (E) a[index];
}
总结
本文对CopyOnWriteArrayList的实现原理和源码进行了分析,并对CopyOnWriteArrayList的优缺点也进行了分析(Java并发包中还提供了CopyOnWriteSet,原理类似)。其实所谓并发容器的优缺点,无非是取决于我们在面对特定并发场景时,是否能做出相对合理的选择和应用。也希望本文能帮助到有需要的童鞋,共勉。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# java
# 并发容器
# CopyOnWriteArrayList
# java中CopyOnWriteArrayList源码解析
# Java并发包之CopyOnWriteArrayList类的深入讲解
# Java源码解析CopyOnWriteArrayList的讲解
# Java concurrency集合之 CopyOnWriteArrayList_动力节点Java学
# Java CopyOnWriteArrayList源码超详细分析
# 加锁
# 将原
# 到新
# 遍历
# 包中
# 很容易
# 很高
# 用在
# 抛出
# 进行了
# 解锁
# 的是
# 都是
# 多写
# 是个
# 是一种
# 却是
# 都要
# 也就
# 一是
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Win11怎么修改DNS服务器 Win11设置DNS加速网络【指南】
Bootstrap整体框架之JavaScript插件架构
JavaScript Ajax实现异步通信
JS经典正则表达式笔试题汇总
laravel怎么配置和使用PHP-FPM来优化性能_laravel PHP-FPM配置与性能优化方法
Laravel如何使用Eloquent进行子查询
Linux虚拟化技术教程_KVMQEMU虚拟机安装与调优
专业企业网站设计制作公司,如何理解商贸企业的统一配送和分销网络建设?
高端建站三要素:定制模板、企业官网与响应式设计优化
JavaScript 输出显示内容(document.write、alert、innerHTML、console.log)
高端智能建站公司优选:品牌定制与SEO优化一站式服务
长沙做网站要多少钱,长沙国安网络怎么样?
今日头条微视频如何找选题 今日头条微视频找选题技巧【指南】
UC浏览器如何切换小说阅读源_UC浏览器阅读源切换【方法】
高性价比服务器租赁——企业级配置与24小时运维服务
东莞市网站制作公司有哪些,东莞找工作用什么网站好?
Laravel的HTTP客户端怎么用_Laravel HTTP Client发起API请求教程
Laravel观察者模式如何使用_Laravel Model Observer配置
消息称 OpenAI 正研发的神秘硬件设备或为智能笔,富士康代工
Linux安全能力提升路径_长期防护思维说明【指导】
绝密ChatGPT指令:手把手教你生成HR无法拒绝的求职信
独立制作一个网站多少钱,建立网站需要花多少钱?
如何快速选择适合个人网站的云服务器配置?
Laravel Eloquent关联是什么_Laravel模型一对一与一对多关系精讲
原生JS获取元素集合的子元素宽度实例
Laravel集合Collection怎么用_Laravel集合常用函数详解
Laravel如何处理跨站请求伪造(CSRF)保护_Laravel表单安全机制与令牌校验
如何快速搭建高效WAP手机网站吸引移动用户?
如何制作公司的网站链接,公司想做一个网站,一般需要花多少钱?
如何在万网ECS上快速搭建专属网站?
Laravel如何实现密码重置功能_Laravel密码找回与重置流程
网站制作怎么样才能赚钱,用自己的电脑做服务器架设网站有什么利弊,能赚钱吗?
如何在云虚拟主机上快速搭建个人网站?
如何在IIS中新建站点并配置端口与IP地址?
敲碗10年!Mac系列传将迎来「触控与联网」双革新
php8.4header发送头信息失败怎么办_php8.4header函数问题解决【解答】
Laravel如何获取当前用户信息_Laravel Auth门面获取用户ID
怎么用AI帮你为初创公司进行市场定位分析?
javascript基于原型链的继承及call和apply函数用法分析
如何在阿里云购买域名并搭建网站?
Laravel如何配置任务调度?(Cron Job示例)
用v-html解决Vue.js渲染中html标签不被解析的问题
Android GridView 滑动条设置一直显示状态(推荐)
如何在阿里云服务器自主搭建网站?
Laravel如何实现邮箱地址验证功能_Laravel邮件验证流程与配置
购物网站制作费用多少,开办网上购物网站,需要办理哪些手续?
Windows10电脑怎么设置虚拟光驱_Win10右键装载ISO镜像文件
如何用JavaScript实现文本编辑器_光标和选区怎么处理
个人网站制作流程图片大全,个人网站如何注销?
如何在VPS电脑上快速搭建网站?

