CopyOnWriteList 容器即写时复制的容器。通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行 Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。这样做的好处是我们可以对 CopyOnWriteList 容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以 CopyOnWrite 容器也是一种读写分离的思想,读和写不同的容器。
CopyOnWriteList 并发容器用于读多写少的并发场景。
public boolean add(E e){
final ReentrantLock lock = this.lock;
lock.lock();
try{
Object[] elements = getArray();
int len = elements.length;
Object[] newEelements = Arrays.copyOf(elements, len+1);
newEelements[len] = e;
setArray(newEelements);
return true;
}finally{
lock.unlock();
}
}
内存占用问题。因为 CopyOnWrite 的写时复制机制,所以在进行写操作的时候,内存里会同时驻扎两个对象的内存,旧的对象和新写入的对象(注意:在复制的时候只是复制容器里的引用,只是在写的时候会创建新对象添加到新容器里,而旧容器的对象还在使用,所以有两份对象内存)数据一致性问题。CopyOnWrite容器只能保证数据的最终一致性,不能保证数据的实时一致性。所以如果你希望写入的的数据,立刻能读到,请不要使用 CopyOnWrite 容器。
CopyOnWriteArraySet 内部完全就是用 CopyOnWriteArrayList 实现的。
public class CopyOnWriteArraySet<E> extends AbstractSet<E>
implements java.io.Serializable {
private static final long serialVersionUID = 5457747651344034263L;
private final CopyOnWriteArrayList<E> al;
.....
}
ConcurrentHashMap 可以高效地支持并发操作,它采用分段锁技术,不是像HashTable一样为几乎每个方法都添加了 synchronized 锁,这会严重影响到性能。
ConcurrentHashMap 的数据结构与 HashMap 基本一致,由链表和红黑树组成。Java8 中当对其中的数据进行 put、remove、replace 时,都会锁住桶结点。例如对 A 桶操作,synchronized(A),对B桶操作 synchronized(B)。使得不同桶之间的操作是可以并发进行。

