1. 简介
在 List中,存在 CopyOnWriteArrayList,其特点是在对List进去修改,都是加锁后将旧数组的元素拷贝到一个新数组进行操作。而 CopyOnWriteArraySet 的底层则是使用 CopyOnWriteArrayList进行实现的。
2. 深入源码
private final CopyOnWriteArrayList<E> al;
public CopyOnWriteArraySet() {
al = new CopyOnWriteArrayList<E>();
}
public CopyOnWriteArraySet(Collection<? extends E> c) {
if (c.getClass() == CopyOnWriteArraySet.class) {
@SuppressWarnings("unchecked") CopyOnWriteArraySet<E> cc =
(CopyOnWriteArraySet<E>)c;
al = new CopyOnWriteArrayList<E>(cc.al);
}
else {
al = new CopyOnWriteArrayList<E>();
al.addAllAbsent(c);
}
}
可以看到CopyOnWriteArraySet就是通过CopyOnWriteArrayList实现的。
我们知道,CopyOnWriteArrayList并不能保证元素是不重复的,那么CopyOnWriteArraySet是如何保证元素是不重复的?
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);
}
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();
}
}
可以看到,CopyOnWriteArraySet 在添加元素时,首先遍历数组中的元素有没有被添加,如果没有被添加则将该元素加入数组,否则,并不重复添加。
总结
(1)CopyOnWriteArraySet并不是使用Map实现的,而是用CopyOnWriteArrayList实现的;
(2)其具有 CopyOnWriteArrayList的特性,对写操作阻塞,读操作不阻塞。
本文详细介绍了CopyOnWriteArraySet的实现原理,它基于CopyOnWriteArrayList,确保元素唯一性。文章分析了其源码,展示了如何在写操作时进行阻塞,避免元素重复添加,同时保持读操作不阻塞。
6543

被折叠的 条评论
为什么被折叠?



