在多线程的环境下,我们大多会用JUC提供的集合工具,比如用CopyOnWriteArrayList
来代替 ArrayList
。
可以避免边读边写时的并发修改异常:ConcurrentModificationException
。
CopyOnWriteArrayList
的实现原理:
底层是一个object数组
,且数组用volatile
修饰,只能通过 getArray/setArray
来访问
/** The array, accessed only via getArray/setArray. */
private transient volatile Object[] array;
/**
* Gets the array. Non-private so as to also be accessible
* from CopyOnWriteArraySet class.
*/
final Object[] getArray() {
return array;
}
/**
* Sets the array.
*/
final void setArray(Object[] a) {
array = a;
}
拿 add()
方法来说
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();
}
}
可以看到,当执行添加操作的时候,他有一把可重入锁,当有线程来执行增加操作的时候获取到这把锁,然后把现有的数据copy
一份放到新的数组里,新数组的容量比旧的数组多一位,这一位用来放需要添加的数据 e
,然后再把新数组赋给原数组,释放锁。