工作原理
- 写时复制:当对
CopyOnWriteArrayList
执行添加、修改或删除操作时,它会先创建一个底层数组的副本,在副本上执行相应操作,操作完成后将原数组引用指向新的副本。例如,调用add
方法时:
public boolean add(E e) {
synchronized (lock) {
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
}
}
- 读操作不加锁:读操作(如
get
方法)直接读取原数组,不会加锁。这是因为写操作是在新的副本上进行,原数组不会被修改,从而保证了读操作的线程安全性和高性能。
public E get(int index) {
return get(getArray(), index);
}
private E get(Object[] a, int index) {
return (E) a[index];
}
适用场景
- 读多写少场景:比如在日志系统中,大量线程可能会频繁读取日志记录,但写入操作相对较少。使用
CopyOnWriteArrayList
可以让读操作无锁执行,提高性能。
- 数据相对稳定场景:像配置信息存储,配置在系统运行期间很少更改,但会被多个线程频繁读取。此时
CopyOnWriteArrayList
能在保证线程安全的同时,提供高效的读性能。