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源码分析的更多相关文章

  1. CopyOnWriteArrayList 源码分析 基于jdk1.8

    CopyOnWriteArrayList  源码分析: 1:成员属性: final transient ReentrantLock lock = new ReentrantLock();  //内部是 ...

  2. JUC之CountDownLatch源码分析

    CountDownLatch是AbstractQueuedSynchronizer中共享锁模式的一个的实现,是一个同步工具类,用来协调多个线程之间的同步.CountDownLatch能够使一个或多个线 ...

  3. CopyOnWriteArrayList源码分析

    基于jdk1.7源码 一.无锁容器 CopyOnWriteArrayList是JDK5中添加的新的容器,除此之外,还有CopyOnWriteArraySet.ConcurrentHahshMap和Co ...

  4. JUC AQS ReentrantLock源码分析

    警告⚠️:本文耗时很长,先做好心理准备,建议PC端浏览器浏览效果更佳. Java的内置锁一直都是备受争议的,在JDK1.6之前,synchronized这个重量级锁其性能一直都是较为低下,虽然在1.6 ...

  5. Java并发编程笔记之CopyOnWriteArrayList源码分析

    并发包中并发List只有CopyOnWriteArrayList这一个,CopyOnWriteArrayList是一个线程安全的ArrayList,对其进行修改操作和元素迭代操作都是在底层创建一个拷贝 ...

  6. JUC之ReentrantLock源码分析

    ReentrantLock:实现了Lock接口,是一个可重入锁,并且支持线程公平竞争和非公平竞争两种模式,默认情况下是非公平模式.ReentrantLock算是synchronized的补充和替代方案 ...

  7. 死磕 java集合之CopyOnWriteArrayList源码分析

    欢迎关注我的公众号"彤哥读源码",查看更多源码系列文章, 与彤哥一起畅游源码的海洋. 简介 CopyOnWriteArrayList是ArrayList的线程安全版本,内部也是通过 ...

  8. 多线程十之CopyOnWriteArrayList源码分析

    目录 简介 类结构 源码解析 构造方法 add(E e) add(int index, E element) get(int index) remove(int index) 迭代器Iterator遍 ...

  9. CopyOnWriteArrayList 源码分析

    CopyOnWriteArrayList CopyOnWriteArrayList 能解决什么问题?什么时候使用 CopyOnWriteArrayList? 1)CopyOnWriteArrayLis ...

随机推荐

  1. 如何获取select下拉框中option选中的文本值

    $(select的id或者class).change(function(){ $(this).find("option:selected").text() }) 源文:https: ...

  2. 运维笔记--linux下忘记mysql root密码

    补充链接:Windows下忘记密码处理: https://www.cnblogs.com/hellojesson/p/5972950.html 场景描述: Linux环境下忘记 root 密码, 1. ...

  3. 爬虫urllib2库的基本使用

    所谓网页抓取,就是把URL地址中指定的网络资源从网络流中读取出来,保存到本地. 在Python中有很多库可以用来抓取网页,urllib2库基本使用. urllib2 是 Python2.7 自带的模块 ...

  4. Excel 相当名称,值相加

    药品名称相同,数量汇总 原始表格,同一个名称,存在不同的单位,所以合并处理成一列 将列表复制一份出去,并删除A表重复数据 求和公式=SUMIF(A2:A16,E2:E8,B2:B16) 最后再将药品名 ...

  5. Swift编码总结5

    1.UIWindow属性: 1>.- (void)becomeKeyWindow;                               // override point for sub ...

  6. LODOP问答部分链接

    点击链接进入相关简短问答博文: 问答大全 纸张打印机 注册 table表格 clodop测试地址 字体 行间距.字间距 clodop回调函数 SET_PRINT_STYLEA 页眉页脚 超文本 条码 ...

  7. notepad++删除某关键字所在的行内容

    例如,我要删除zhao这个字符串所在的行 打开notepad++的ctrl+f窗口 点击替换选项,在查找目标输入^.*bp.*$ 其中替换为那里留空,查找模式选择正则表达式,建议也勾选匹配大小写,同时 ...

  8. [LeetCode] 149. Max Points on a Line 共线点个数

    Given n points on a 2D plane, find the maximum number of points that lie on the same straight line. ...

  9. 后会有期,江湖再见!(WondersGroup)

    很高兴能和大家一路走来,一如既往的做好并做完本职工作后,今儿我要离开了,本想着悄无声息地离开,但是为了解决走了还被微信艾特和私聊找我处理问题的潜在风险,我决定在此正式的和大家说一声再见!哈哈,It's ...

  10. ObjectARX开发VC版本对照表R14~AutoCAD2020