1.概述
在很多应用场景中,读操作可能会远远大于写操作。由于读操作根本不会修改原有的数据,因此如果每次读取都进行加锁操作,其实是一种资源浪费。我们应该允许多个线程同时访问 List 的内部数据,毕竟读操作是线程安全的。
2.读写分离思想
为了将读取的性能发挥到极致,CopyOnWriteArrayList 读取是完全不用加锁的,并且写入也不会阻塞读取操作,只有写入和写入之间需要进行同步等待,读操作的性能得到大幅度提升。
当CopyOnWriteArrayList调用add或者set操作的时候,首先会将原数组复制一份进行操作,操作完成后会更新原数组的引用,使用新数组,原数组数据内存释放,由于add/set操作的时候加入了锁机制所以会阻塞另一个线程的add/set操作,因为读操作没有加锁操作,所以可能会出现A线程读取数据的时候,B线程更新了数据但还没来得及更新原数组引用而造成读脏数据的问题,这就是所谓的读取了脏数据.
所以CopyOnWriteArrayList适合读操作远远多于写操作的业务情景。
3.talk is cheap,show me code
/** The array, accessed only via getArray/setArray. */
private transient volatile Object[] array;
public E get(int index) {
return get(getArray(), index);
}
@SuppressWarnings("unchecked")
private E get(Object[] a, int index) {
return (E) a[index];
}
final Object[] getArray() {
return array;
}
网友评论