Copy-On-Write(COW):
开始时共享同一资源,但一个线程修改部分内容时,才会用修改后的内容覆盖旧的内容.是一种延时懒惰策略.
有两种COW机制的并发容器:
CopyOnWriteArrayList
.CopyOnWriteArraySet
.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(); // 释放锁
}
}
步骤:
public E get(int index) {
return get(getArray(), index);
}
注: 获取元素无需加锁.
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 { // 若指定位置的元素与设定的元素相同,则无需更新
setArray(elements);
}
return oldValue;
} finally {
lock.unlock(); // 释放锁
}
}
步骤:
类似与添加元素.
private boolean addIfAbsent(E e, Object[] snapshot) {
final ReentrantLock lock = this.lock;
lock.lock(); // 加锁
try {
Object[] current = getArray();
int len = current.length;
if (snapshot != current) {
int common = Math.min(snapshot.length, len);
for (int i = 0; i < common; i++)
if (current[i] != snapshot[i] && eq(e, current[i]))
return false;
if (indexOf(e, current, common, len) >= 0)
return false;
}
Object[] newElements = Arrays.copyOf(current, len + 1); // 复制旧容器中的元素
newElements[len] = e; // 向新容器中新增元素
setArray(newElements); // 更新引用
return true;
} finally {
lock.unlock(); // 解锁
}
}
流程:
参考:
原文:https://www.cnblogs.com/truestoriesavici01/p/13216170.html