我是靠谱客的博主 妩媚小虾米,最近开发中收集的这篇文章主要介绍CopyOnWrite机制,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

CopyOnWrite容器

通俗地讲,当我们往容器中添加一个元素的时候,不是直接添加,而是对当前容器copy,复制一个容器,在这个复制的容器中添加元素,添加完之后,再将引用指向这个新容器。

优点:CopyOnWrite容器可以并发的进行读操作,而不需要加锁,因为 当前容器不会添加任何元素,所以这也是一种读写分离的思想,读和写的操作分开了。

缺点:

1.内存占用问题,产生了两个容器

2.只能保持数据的最终一致性,无法保持 实时性,所以如果希望读到新数据,不要用copyOnWrite

CopyOnWrite应用场景

用于读多写少的场景,比如白名单,黑名单,搜索中有一些关键字不可以搜索,这些关键字放在一个黑名单中,只有偶尔才更新黑名单

CopyOnWriteArrayList

来看CopyOnWriteArrayList的源码

add方法加锁,如果不加锁,就会copy出很多副本,然后把元素放在新容器,最后把引用指向了新容器

get方法没有锁,简单的从数组中获取元素。但注意,此时如果有其他线程往容器添加元素,它无法获取到新数据,只能获取到旧数据

public class CopyOnWriteArrayList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
private static final long serialVersionUID = 8673264195747942595L;
/** The lock protecting all mutators */
final transient ReentrantLock lock = new ReentrantLock();
/** The array, accessed only via getArray/setArray. */
private transient volatile Object[] array;
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();
}
}
final void setArray(Object[] a) {
array = a;
}
@SuppressWarnings("unchecked")
private E get(Object[] a, int index) {
return (E) a[index];
}
/**
* {@inheritDoc}
*
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E get(int index) {
return get(getArray(), index);
}
}

CopyOnWriteArraySet

set的特点是去重。CopyOnWriteArraySet是用了装饰者模式,内部其实引用了一个CopyOnWriteArrayList,add方法是用了CopyOnWriteArrayList的addIfAbsent方法,如果元素不存在,才加入容器

public class CopyOnWriteArraySet<E> extends AbstractSet<E>
implements java.io.Serializable {
private static final long serialVersionUID = 5457747651344034263L;
private final CopyOnWriteArrayList<E> al;
public CopyOnWriteArraySet() {
al = new CopyOnWriteArrayList<E>();
}
public boolean add(E e) {
return al.addIfAbsent(e);
}
}
public boolean addIfAbsent(E e) {
Object[] snapshot = getArray();
return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false :
addIfAbsent(e, snapshot);
}
/**
* A version of addIfAbsent using the strong hint that given
* recent snapshot does not contain e.
*/
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) {
// Optimize for lost race to another addXXX operation
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();
}
}

 

最后

以上就是妩媚小虾米为你收集整理的CopyOnWrite机制的全部内容,希望文章能够帮你解决CopyOnWrite机制所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(54)

评论列表共有 0 条评论

立即
投稿
返回
顶部