瞄一眼CopyOnWriteArrayList(jdk11)
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)的更多相关文章
- 瞄一眼LongAdder(jdk11)
java版本11.0.1,感觉写得太水了,等心情好的时候再重新编辑一下. LongAdder中的核心逻辑主要由java.util.concurrent.atomic.Striped64维护,作为Str ...
- 瞄一眼,带你走进SparkSQL的世界
本文由 网易云发布. 作者:范欣欣(本篇文章仅限知乎内部分享,如需转载,请取得作者同意授权.) 最近想来,大数据相关技术与传统型数据库技术很多都是相互融合.互相借鉴的.传统型数据库强势在于其久经考验 ...
- 后HTML5时代
十二年前,无论多么复杂的布局,在我们神奇的table面前,都不是问题:十年前,阿捷的一本<网站重构>,为我们开启了新的篇章:八年前,我们研究yahoo.com,惊叹它在IE5下都表现得如此 ...
- [深入JUnit] 测试运行的入口
阅读前提 了解JUnit 对JUnit的内部实现有兴趣 不妨看看[深入JUnit] @Before, @After, @Test的秘密] 代码版本: junit 4.12代码搜索工具: http:// ...
- Intellij IDEA 一些不为人知的技巧
Intellij IDEA 一些不为人知的技巧 2016/12/06 | 分类: 基础技术 | 0 条评论 | 标签: IntelliJ 分享到:38 原文出处: khotyn 今天又听了 Jetbr ...
- jq绑定事件的4种方式
jQuery提供了多种绑定事件的方式,每种方式各有其特点,明白了它们之间的异同点,有助于我们在写代码的时候进行正确的选择,从而写出优雅而容易维护的代码.下面我们来看下jQuery中绑定事件的方式都有哪 ...
- [No00007D]2016-面经[上]
面试常见问题: 题一:"请你自我介绍一下" 思路:1.这是面试的必考题目.2.介绍内容要与个人简历相一致.3.表述方式上尽量口语化.4.要切中要害,不谈无关.无用的内容.5.条理要 ...
- [No00006D]下载离线版的github for windows【以Github for Windows 3.0.110.为例】
目录 先上地址后讲原理: 原理: 11个目录的文件怎么一口气下载呢? 最后,把下好的文件批量名,同时将GitHub.exe.manifest也放到软件根目录下(与GitHub.exe同级): 今后的猜 ...
- Linux 小命令
查看 cat 文件名 [查看里面的内容,cate,猫,像猫一样瞄一眼的看] more 文件名 [查看文件,文件太多,一次看不完,用 more 来查看 下一页:空格或 f 下一行:回车 ...
随机推荐
- 动态代理--Cglib
JDK 的Proxy 实现,需要代理对象实现接口: package com.utils; import java.lang.reflect.InvocationHandler; import java ...
- PAT (Basic Level) Practise (中文)- 1011. A+B和C (15)
http://www.patest.cn/contests/pat-b-practise/1011 给定区间[-231, 231]内的3个整数A.B和C,请判断A+B是否大于C. 输入格式: 输入第1 ...
- java基础—java制作证书的工具keytool
一.keytool的概念 keytool 是个密钥和证书管理工具.它使用户能够管理自己的公钥/私钥对及相关证书,用于(通过数字签名)自我认证(用户向别的用户/服务认证自己)或数据完整性以及认证服务.在 ...
- java利用SuffixFileFilter统计目录下特定后缀名文件的数目
/** * 文件处理类 * @author zhangcd * @date 2017年1月3日 */ public class FileUtil { /** * 得到所有后缀的数目 * * @para ...
- 这一千个Python库,总有你想要的!
环境管理 管理 Python 版本和环境的工具 p – 非常简单的交互式 python 版本管理工具. pyenv – 简单的 Python 版本管理工具. Vex – 可以在虚拟环境中执行命令. v ...
- Altium Designer入门学习笔记1.软件安装与资料收集
一.软件安装 微信:http://url.cn/5Eudzt9 关注微信公众号"软件安装管家",点击"软件目录",弹出"软件目录",点击进入 ...
- 某比赛小记1- 挑选第N大数字
题目:给1000个数字(有重复),从小到大排列后,挑选第N个数字. 数字文件如下:numbers.rar ,挑选第727个数字. java版本: //数组初始化 String str = " ...
- emacs写cnblog博客
emacs的版本 org-mode版本 参考链接: 用Emacs管理博客园博客 用emacs org-mode写cnblogs博客 用emacs org-mode写博客 & 发布到博客 ...
- 有限状态机(FSM)的设计与实现
有限状态机(FSM)是表示有限个状态及在这些状态之间的转移和动作等行为的数学模型,在计算机领域有着广泛的应用.通常FSM包含几个要素:状态的管理.状态的监控.状态的触发.状态触发后引发的动作.本文主要 ...
- “万恶”的break
写这篇随笔主要是希望自己长点记性,break的作用是跳出当次循环,每次用break都有点忘记break后面的条件提前. 正常是这样: exit_flag=Falsefor i in range(10) ...