ArrayList 的一个线程安全的变体,其中所有可变操作(add、set 等等)都是通过对底层数组进行一次新的复制来实现的。
上面这句话是官方jdk里写的 其实就是copyonwritelist是一个安全类 每次都是通过复制来实现线程安全
打开copyonwritelist的源码
/** The lock protecting all mutators */
final transient ReentrantLock lock = new ReentrantLock();
/** The array, accessed only via getArray/setArray. */
private transient volatile Object[] array;
发现了这两个成员变量 从注释上来看 copyonwritelist中的数据主要就是存储在这个array中 加上volatile是让多个线程可见
而ReentrantLock 则是使用了显示锁
我们先看看add方法
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return {@code true} (as specified by {@link Collection#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();
}
}
这个可以看到 这个方法在替换整个arr数组 整个方法进行使用了显示锁进行锁定
而我们的get方法则不会进行锁定 这是为什么呢
因为每次调用get的时候对象都是不变的