CopyOnWriteArrayList是ArrayList线程安全的变体。使用写时复制策略进行修改操作。

与之前版本较明显的区别是,jdk11中用来保护所有设值方法(mutator)的ReentrantLock改为使用关键字synchronized。

文档中也明确表示相比较于ReentrantLock更倾向于使用内置锁(We have a mild preference for builtin monitors over ReentrantLock when either will do.)。

两个都是可重入独占锁,在不涉及到中断、超时等情况时,编码时使用synchronized明显比ReentrantLock优势得多。

CopyOnWriteArrayList的成员变量:

    //锁对象
final transient Object lock = new Object(); //存储数据的数组
private transient volatile Object[] array; final Object[] getArray() {
return array;
} final void setArray(Object[] a) {
array = a;
}

第一个Object对象充当写时复制的锁对象,第二个volatile的array用来存放数据

挑个构造函数看看:

     /**
* 根据Collection迭代器返回的顺序创建包含指定集合元素的列表
*
* @param c 最初保存元素的集合
* @throws NullPointerException 如果指定的集合为null
*/
public CopyOnWriteArrayList(Collection<? extends E> c) {
Object[] es;
if (c.getClass() == CopyOnWriteArrayList.class)
es = ((CopyOnWriteArrayList<?>)c).getArray(); //同类对象直接获取array赋值
else {
es = c.toArray();
// defend against c.toArray (incorrectly) not returning Object[]
// (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652)
if (es.getClass() != Object[].class)
es = Arrays.copyOf(es, es.length, Object[].class);
}
setArray(es); //array赋值
}

注释中说,L15的条件分支是为了解决Collection.toArray()没有正确地返回为Object[]类型,而是错误地返回为Object类型。这个bug在jdk9已经被修复了。不知道为什么在11.0.2还留着。

jdk中的//单行注释一般都挺有意思的…

读操作和ArrayList没多大差别,所以都是弱一致性的。挑几个写操作看看:

   public void add(int index, E element) {
synchronized (lock) { //获取独占锁
Object[] es = getArray();
int len = es.length;
if (index > len || index < 0) { //越界校验
throw new IndexOutOfBoundsException(outOfBounds(index, len));
}
Object[] newElements;
int numMoved = len - index;
if (numMoved == 0) { //若index=array.length,则新元素添加在末尾
newElements = Arrays.copyOf(es, len + 1);
} else {
newElements = new Object[len + 1]; //创建array副本,调用System.arraycopy()移动index后元素添加新元素于index
System.arraycopy(es, 0, newElements, 0, index);
System.arraycopy(es, index, newElements, index + 1, numMoved);
}
newElements[index] = element;
setArray(newElements); //将修改后的array副本回写给array
}
}
   public E set(int index, E element) {
synchronized (lock) { //获取独占锁
Object[] es = getArray();
E oldValue = elementAt(es, index); //找出index位置的元素
if (oldValue != element) { //如果元素与原先元素不同,则创建array副本。在副本修改后写回array
es = es.clone();
es[index] = element;
setArray(es);
}
return oldValue;
}
}

值得注意的是,之前版本的set方法在上段代码L9多了个分支:

} else {
// Not quite a no-op; ensures volatile write semantics
setArray(elements);
}

注释说了,setArray()是为了保持volatile写的语义,即内存一致性:当存在并发时,将对象放入CopyOnWriteArrayList之前的线程中的操作happen-before随后通过另一线程从CopyOnWriteArrayList中访问或移除该元素的操作。由于jdk11使用synchronized替代了ReentrantLock,也就不需要这一段了。

瞄一眼CopyOnWriteArrayList(jdk11)的更多相关文章

  1. 瞄一眼LongAdder(jdk11)

    java版本11.0.1,感觉写得太水了,等心情好的时候再重新编辑一下. LongAdder中的核心逻辑主要由java.util.concurrent.atomic.Striped64维护,作为Str ...

  2. 瞄一眼,带你走进SparkSQL的世界

    本文由  网易云发布. 作者:范欣欣(本篇文章仅限知乎内部分享,如需转载,请取得作者同意授权.) 最近想来,大数据相关技术与传统型数据库技术很多都是相互融合.互相借鉴的.传统型数据库强势在于其久经考验 ...

  3. 后HTML5时代

    十二年前,无论多么复杂的布局,在我们神奇的table面前,都不是问题:十年前,阿捷的一本<网站重构>,为我们开启了新的篇章:八年前,我们研究yahoo.com,惊叹它在IE5下都表现得如此 ...

  4. [深入JUnit] 测试运行的入口

    阅读前提 了解JUnit 对JUnit的内部实现有兴趣 不妨看看[深入JUnit] @Before, @After, @Test的秘密] 代码版本: junit 4.12代码搜索工具: http:// ...

  5. Intellij IDEA 一些不为人知的技巧

    Intellij IDEA 一些不为人知的技巧 2016/12/06 | 分类: 基础技术 | 0 条评论 | 标签: IntelliJ 分享到:38 原文出处: khotyn 今天又听了 Jetbr ...

  6. jq绑定事件的4种方式

    jQuery提供了多种绑定事件的方式,每种方式各有其特点,明白了它们之间的异同点,有助于我们在写代码的时候进行正确的选择,从而写出优雅而容易维护的代码.下面我们来看下jQuery中绑定事件的方式都有哪 ...

  7. [No00007D]2016-面经[上]

    面试常见问题: 题一:"请你自我介绍一下" 思路:1.这是面试的必考题目.2.介绍内容要与个人简历相一致.3.表述方式上尽量口语化.4.要切中要害,不谈无关.无用的内容.5.条理要 ...

  8. [No00006D]下载离线版的github for windows【以Github for Windows 3.0.110.为例】

    目录 先上地址后讲原理: 原理: 11个目录的文件怎么一口气下载呢? 最后,把下好的文件批量名,同时将GitHub.exe.manifest也放到软件根目录下(与GitHub.exe同级): 今后的猜 ...

  9. Linux 小命令

    查看 cat  文件名     [查看里面的内容,cate,猫,像猫一样瞄一眼的看] more 文件名   [查看文件,文件太多,一次看不完,用 more 来查看 下一页:空格或 f   下一行:回车 ...

随机推荐

  1. Tarjan 详解

    Tarjan 算法 一.算法简介 Tarjan 算法一种由Robert Tarjan提出的求解有向图强连通分量的算法,它能做到线性时间的复杂度. 我们定义: 如果两个顶点可以相互通达,则称两个顶点强连 ...

  2. jfinal的配置文件详解

    1.去官网下载最新的jar包(我这是JFinal-lib-2.2) tomcat+mysql 所需要的jar 2.配置web.xml <filter> <filter-name> ...

  3. Luogu [P3367] 模板 并查集

    [模板]并查集 题目详见:[[P3367][模板]并查集] (https://www.luogu.org/problemnew/show/P3367) 这是一道裸的并查集题目(要不然叫模板呢) 废话不 ...

  4. jenkins 插件

  5. Vim编辑器基础

    Vim编辑器基础 vi:Visual Interface vim:VI iMproved Vim模式 1.编辑模式(命令模式) 只能下达命令,不能键入字符 2.输入模式 键入字符 3.末行模式 左下角 ...

  6. 模拟发送http请求的工具推荐

    做网站开发时,经常需要发送请求来测试自己的代码是否OK,这时候模拟发送http请求的工具就起到了很大的作用.特别是需要在请求带header时就更加的有必要使用工具.下面推荐的工具有的是基于系统开发的程 ...

  7. 【Spring】事务的实现方式

    1 初步理解 理解事务之前,先讲一个你日常生活中最常干的事:转账. 场景设定: 用户名 余额 A 1000 B 1000 操作: A通过支付宝给B转账200块,做这件事情会进行两个操作. 1:A账号- ...

  8. DeepFaceLab: SSE,AVX, OpenCL 等版本说明!

    Deep Fake Lab早期只有两个版本,一个是专门正对NVIDIA显卡的CUDA9的版本,另一个是支持CPU的版本. 三月初该项目作者对tenserFlow,Cuda的版本进行了升级,预编译的软件 ...

  9. 《零基础入门学习Python》【第一版】视频课后答案第001讲

    测试题答案: 0. Python 是什么类型的语言? Python是脚本语言 脚本语言(Scripting language)是电脑编程语言,因此也能让开发者藉以编写出让电脑听命行事的程序.以简单的方 ...

  10. hdu 6333

    Problem Description There are n apples on a tree, numbered from 1 to n.Count the number of ways to p ...