在多线程的环境下,我们大多会用JUC提供的集合工具,比如用CopyOnWriteArrayList来代替 ArrayList
可以避免边读边写时的并发修改异常:ConcurrentModificationException

CopyOnWriteArrayList的实现原理:

底层是一个object数组,且数组用volatile修饰,只能通过 getArray/setArray 来访问

  1. /** The array, accessed only via getArray/setArray. */
  2. private transient volatile Object[] array;
  3. /**
  4. * Gets the array. Non-private so as to also be accessible
  5. * from CopyOnWriteArraySet class.
  6. */
  7. final Object[] getArray() {
  8. return array;
  9. }
  10. /**
  11. * Sets the array.
  12. */
  13. final void setArray(Object[] a) {
  14. array = a;
  15. }

add() 方法来说

  1. public boolean add(E e) {
  2. final ReentrantLock lock = this.lock;
  3. lock.lock();
  4. try {
  5. Object[] elements = getArray();
  6. int len = elements.length;
  7. Object[] newElements = Arrays.copyOf(elements, len + 1);
  8. newElements[len] = e;
  9. setArray(newElements);
  10. return true;
  11. } finally {
  12. lock.unlock();
  13. }
  14. }

可以看到,当执行添加操作的时候,他有一把可重入锁,当有线程来执行增加操作的时候获取到这把锁,然后把现有的数据copy一份放到新的数组里,新数组的容量比旧的数组多一位,这一位用来放需要添加的数据 e ,然后再把新数组赋给原数组,释放锁。