【JUC】8.CopyOnWriteArrayList源码分析
CopyOnWriteArrayList
解决脏读问题;牺牲写的效率,提高读的效率
CopyOnWriteArrayList是一种读写分离的思想体现的ArrayList;
它将读写的操作对象分离开来;
写的过程中,通过复制出一片新的内存,在新的内存中执行完成写操作,再赋值回去,完成写操作;
在写的过程中,可以进行并发的读,因为操作的并不是同一片内存;
这样就避免了java.util.ConcurrentModificationException并发修改异常了;
下面一步步来看一下源码,怎么实现的?
只分析了部分常用的API的源码:读取get和写入add
构造器
直接看源码,不是很复杂;
public class CopyOnWriteArrayList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable { final transient ReentrantLock lock = new ReentrantLock();
private transient volatile Object[] array; //数据都会存储在这个array中
// 提供set,get方法
final Object[] getArray() {
return array;
}
final void setArray(Object[] a) {
array = a;
}
// ①无参构造器
public CopyOnWriteArrayList() {
setArray(new Object[0]); // 初始化一个长度0的array
}
// ②将一个Collection转化为CopyOnWriteArrayList
public CopyOnWriteArrayList(Collection<? extends E> c) {
Object[] elements;
// 此Collection就是CopyOnWriteArrayList,直接赋值
if (c.getClass() == CopyOnWriteArrayList.class)
elements = ((CopyOnWriteArrayList<?>)c).getArray();
else {
// 其余都转化为Object数组赋值
elements = c.toArray();
if (elements.getClass() != Object[].class)
elements = Arrays.copyOf(elements, elements.length, Object[].class);
}
setArray(elements);
}
// ③直接传入一个泛型数组
public CopyOnWriteArrayList(E[] toCopyIn) {
setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class));
}
add
添加方法,此类的重点方法:即:写操作的实现;
CopyOnWrite容器,即写时复制的容器;
添加元素的时候,并不直接添加,而是先将array复制一份给 Object[ ] newElements,且newElements长度加1,表示要添加一个元素;
添加的操作,都是针对newElements进行的,不对原array进行操作;
这样就将,写操作的内存,与读操作的内存分离开来,写的过程不会影响并发读取;
源码:
// 添加方法
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();// 枷锁
try {
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);//复制出一个newElements
newElements[len] = e;// 添加元素
setArray(newElements);// 将添加完成的newElements赋值给原array
return true;
} finally {
lock.unlock();
}
}
final Object[] getArray() {
return array;
}
final void setArray(Object[] a) {
array = a;
}
get
读取操作,没有做任何的同步措施;
array并不会发生修改,只会在写操作后,直接替换,不存在数据安全问题;
public E get(int index) {
return get(getArray(), index);
}
private E get(Object[] a, int index) {
return (E) a[index];
}
final Object[] getArray() {
return array;
}
【JUC】8.CopyOnWriteArrayList源码分析的更多相关文章
- CopyOnWriteArrayList 源码分析 基于jdk1.8
CopyOnWriteArrayList 源码分析: 1:成员属性: final transient ReentrantLock lock = new ReentrantLock(); //内部是 ...
- JUC之CountDownLatch源码分析
CountDownLatch是AbstractQueuedSynchronizer中共享锁模式的一个的实现,是一个同步工具类,用来协调多个线程之间的同步.CountDownLatch能够使一个或多个线 ...
- CopyOnWriteArrayList源码分析
基于jdk1.7源码 一.无锁容器 CopyOnWriteArrayList是JDK5中添加的新的容器,除此之外,还有CopyOnWriteArraySet.ConcurrentHahshMap和Co ...
- JUC AQS ReentrantLock源码分析
警告⚠️:本文耗时很长,先做好心理准备,建议PC端浏览器浏览效果更佳. Java的内置锁一直都是备受争议的,在JDK1.6之前,synchronized这个重量级锁其性能一直都是较为低下,虽然在1.6 ...
- Java并发编程笔记之CopyOnWriteArrayList源码分析
并发包中并发List只有CopyOnWriteArrayList这一个,CopyOnWriteArrayList是一个线程安全的ArrayList,对其进行修改操作和元素迭代操作都是在底层创建一个拷贝 ...
- JUC之ReentrantLock源码分析
ReentrantLock:实现了Lock接口,是一个可重入锁,并且支持线程公平竞争和非公平竞争两种模式,默认情况下是非公平模式.ReentrantLock算是synchronized的补充和替代方案 ...
- 死磕 java集合之CopyOnWriteArrayList源码分析
欢迎关注我的公众号"彤哥读源码",查看更多源码系列文章, 与彤哥一起畅游源码的海洋. 简介 CopyOnWriteArrayList是ArrayList的线程安全版本,内部也是通过 ...
- 多线程十之CopyOnWriteArrayList源码分析
目录 简介 类结构 源码解析 构造方法 add(E e) add(int index, E element) get(int index) remove(int index) 迭代器Iterator遍 ...
- CopyOnWriteArrayList 源码分析
CopyOnWriteArrayList CopyOnWriteArrayList 能解决什么问题?什么时候使用 CopyOnWriteArrayList? 1)CopyOnWriteArrayLis ...
随机推荐
- Centos7搭建FTP服务详细过程
Centos7搭建FTP服务详细过程https://blog.csdn.net/sinat_30802291/article/details/81706152
- Linux目录结构和作用
转载自:https://blog.csdn.net/wangrongrongwq/article/details/79624797 [常见目录说明] 目录 /bin 存放二进制可执行文件(ls,cat ...
- 转:laydate只显示时分,不显示秒
@转载地址 原文全文: 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/weixin_40 ...
- 改进初学者的PID-测量的比例编码
最近看到了Brett Beauregard发表的有关PID的系列文章,感觉对于理解PID算法很有帮助,于是将系列文章翻译过来!在自我提高的过程中,也希望对同道中人有所帮助.作者Brett Beaure ...
- JavaScript和Jquery个人笔记
目录 前言 价格 * 数量 = 金额 js计算时间差值 判断敲回车或Shift+回车 js控制textarea换行 $(this)选择当前元素 前端调试禁止其他js js添加a标签href属性和文本 ...
- python断点
pycharm怎么debug单步调试 1.打开一个Pycharm的界面,需要选中编辑器中的左侧. 2.点击Run---->Debug运行 3.点击箭头,向下运行 4.可以看到代码运行到下一条 5 ...
- MinGW ,GNU 是什么
MinGW : Minimalist GNU for Windows MinGW(Minimalist GNU For Windows)是个精简的Windows平台下的 C/C++.ADA及Fortr ...
- python学习-68 反射
反射 1.什么是反射? 反射的概念是有Smith在1982年首次提出的,主要是指程序可以访问.检测和修正它本身状态或行为的一种能力(自省). 2.以下四个方法可以实现自省 hasattr(object ...
- pandas.DataFrame对象解析
pandas.DataFrame对象类型解析 df = pd.DataFrame([[1,"2",3,4],[5,"6",7,8]],columns=[&quo ...
- MySQL练手小试题
创建表和数据 创建class表 create table class ( cid int(11) primary key auto_increment, caption varchar(32) not ...