在多线程的环境下,我们大多会用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 ,然后再把新数组赋给原数组,释放锁。
