回复
为什么有了并发安全的集合还需要读写锁?(一)
pivoteic
发布于 2022-6-16 17:48
浏览
0收藏
大家好,我是三友,这篇文章想来跟大家来探讨一下,在Java中已经提供了并发安全的集合,为什么有的场景还需要使用读写锁,直接用并发安全的集合难道不行么?
在java中,并发安全的集合有很多,这里我就选用常见的CopyOnWriteArrayList为例,来说明一下读写锁的价值到底提现在哪。
CopyOnWriteArrayList核心源码分析
接下来我们分析一下CopyOnWriteArrayList核心的增删改查的方法
成员变量
//独占锁
final transient ReentrantLock lock = new ReentrantLock();
//底层用来存放元素的数组
private transient volatile Object[] array;
add方法:往集合中添加某个元素
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[len] = e;
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}
add操作先通过lock加锁,保证同一时刻最多只有一个线程可以操作。加锁成功获取到成员变量的数据,然后拷贝成员变量数组的元素到新的数组,再基于新的数据来添加元素,最后将新拷贝的数组通过setArray来替换旧的成员变量的数组。
remove方法:移除集合中的某个元素
public E remove(int index) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
E oldValue = get(elements, index);
int numMoved = len - index - 1;
if (numMoved == 0)
setArray(Arrays.copyOf(elements, len - 1));
else {
Object[] newElements = new Object[len - 1];
System.arraycopy(elements, 0, newElements, 0, index);
System.arraycopy(elements, index + 1, newElements, index,
numMoved);
setArray(newElements);
}
return oldValue;
} finally {
lock.unlock();
}
}
remove操作也要先获取到锁。它先是取出对应数组下标的旧元素,然后新建了一个原数组长度减1的新数组,将除了被移除的元素之外,剩余的元素拷贝到新的数组,最后再通过setArray替换旧的成员变量的数组。
set方法:将集合中指定位置的元素替换成新的元素
public E set(int index, E element) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
E oldValue = get(elements, index);
if (oldValue != element) {
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len);
newElements[index] = element;
setArray(newElements);
} else {
// Not quite a no-op; ensures volatile write semantics
setArray(elements);
}
return oldValue;
} finally {
lock.unlock();
}
}
文章转自公众号:三友的java日记
标签
已于2022-6-16 17:48:08修改
赞
收藏
回复
相关推荐