Java中的Copy-On-Write集合(CopyOnWriteArrayList)?
请解释Java并发集合中的**Copy-On-Write(写时复制)**机制,以CopyOnWriteArrayList为例,说明其读/写操作的实现原理、适用场景(读多写少)、以及相比于Collections.synchronizedList()的优势和不足。
回答
古法程序员
CopyOnWriteArrayList:线程安全的ArrayList变体,采用写时复制策略。
实现原理:
- 底层:volatile transient Object[] array
- 读操作:不加锁,直接读array引用(由于volatile保证可见性)
- 写操作(add/set/remove):加ReentrantLock锁,复制整个数组为副本,在副本上修改,然后将副本赋值给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);
} finally {
lock.unlock();
}
}
特点:
- 读操作无锁(高性能)
- 写操作复制整个数组(性能低,内存开销大)
- 弱一致性:迭代器遍历的是创建时的快照,不会抛ConcurrentModificationException
- 适用场景:读多写少(如白名单、配置信息)
vs synchronizedList():
- synchronizedList读也要加锁,并发读性能差
- CopyOnWriteArrayList读完全无锁,适合读频繁场景
- 写操作频繁时不合适(频繁复制数组代价大)