CopyOnWriteArrayList
- CopyOnWriteArrayList 线程安全
- 使用分析
- 优点
- 性能高:读取没有锁,更改才有锁
- 读写隔离高:更改时不影响正常读取
- 缺点
- 性能问题:不适合写操作多场景,导致复制次数多,性能低
- 内存问题:不适合数据量大的场景,导致每次复制时占用内存多
- 数据弱一致性: 不支持快速失败机制,在修改操作开始和结束之间读取的都是老数据
- 适用场景:写操作不多,数据量不大,内存资源充足的情况
- 优点
- 设计分析
- 设计目标
- List可以同时达到多线程的安全和性能的高效
- 设计思路
- 要解决的问题
- 多线程安全问题和性能高效问题
- 解决问题的思路
- 读取操作不加锁,修改操作加锁但不能影响读取操作。
- 解决问题的方案
- Coyp On Write 方案解决修改时的多线程安全问题,并保证修改时不影响读取操作
- 要解决的问题
- 实现原理
- 读取没有锁
- 添加和删除时使用ReentrantLock锁
- 每次添加和删除时使用Arrays.copyOf()生成只多一个或者少一个长度的数组,没有倍数扩容和缩容
- 更改操作完成后,将老数组指针指向新数组
- 基于Object[]实现
- 设计目标
- 源码分析
- 继承关系
- public class CopyOnWriteArrayList<E>
extends Object
implements List<E>, RandomAccess, Cloneable, Serializable
- public class CopyOnWriteArrayList<E>
- add方法
- public boolean add(E e) {
final ReentrantLock lock = this.lock;
// 加锁
lock.lock();
try {
// 获取原来的数组
Object[] elements = getArray();
// 原来数组的长度
int len = elements.length;
// 创建一个长度+1的新数组,并将原来数组的元素复制给新数组
Object[] newElements = Arrays.copyOf(elements, len + 1);
// 元素放在新数组末尾
newElements[len] = e;
// array指向新数组
setArray(newElements);
return true;
} finally {
// 解锁
lock.unlock();
}
}
- public boolean add(E e) {
- 删除方法
- public E remove(int index) {
// 获取可重入锁
final ReentrantLock lock = this.lock;
// 加锁
lock.lock();
try {
//获取当前array数组
Object[] elements = getArray();
// 获取当前array长度
int len = elements.length;
//获取指定索引的元素(旧值)
E oldValue = get(elements, index);
int numMoved = len - index - 1;
// 判断删除的是否是最后一个元素
if (numMoved == 0)
// 如果删除的是最后一个元素,直接复制该元素前的所有元素到新的数组
setArray(Arrays.copyOf(elements, len - 1));
else {
// 分段复制,将index前的元素和index+1后的元素复制到新数组
// 新数组长度为旧数组长度-1
Object[] newElements = new Object[len - 1];
System.arraycopy(elements, 0, newElements, 0, index);
System.arraycopy(elements, index + 1, newElements, index,
numMoved);
//将新数组赋值给array引用
setArray(newElements);
}
return oldValue;
} finally {
// 解锁
lock.unlock();
}
}
- public E remove(int index) {
- 继承关系
- https://javaguide.cn/java/collection/copyonwritearraylist-source-code.html
- 使用分析
作者: 一点点征服
出处:http://www.cnblogs.com/ldq2016/
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利