成员变量
//CopyOnWriteArrayList内部持有一个重入锁,用于保证线程安全
final transient ReentrantLock lock = new ReentrantLock();
//数组,注意用volatile修饰了,保证了可见性,所以在读这个数组时是不用加锁的
private transient volatile Object[] array;
构造方法
//为成员变量array赋值了一个空数组
public CopyOnWriteArrayList() {
setArray(new Object[0]);
}
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;
//直接把旧数组中的元素复制到长度+1的新数组中
Object[] newElements = Arrays.copyOf(elements, len + 1);
//把插入的元素放在新数组末尾
newElements[len] = e;
//设置array指向新的数组
setArray(newElements);
return true;
} finally {
//释放锁放在finally块中,以保证异常情况下也能释放锁
lock.unlock();
}
}
//直接返回array数组
final Object[] getArray() {
return array;
}
这里可以看出CopyOnWriteArrayList名字的由来:在写入的时候进行数组拷贝
可以发现,CopyOnWriteArrayList中并没有采用ArrayList中的1.5倍空间预分配策略
get方法
public E get(int index) {
return get(getArray(), index);
}
//直接通过下表从数组中取元素并返回,由于数组用volatile修饰,所以不需要加锁也能保证读操作的线程安全
private E get(Object[] a, int index) {
return (E) a[index];
}
size方法和isEmpty方法
//直接返回数组长度,也不用加锁
public int size() {
return getArray().length;
}
//判断size是否为0即可
public boolean isEmpty() {
return size() == 0;
}