您的位置:首页 > 运维架构

学学JUC(三)-- CopyOnWriteArrayList和CopyOnWriteArraySet

2015-02-11 21:37 375 查看
CopyOnWriteArrayList是基于“写时复制”策略的线程安全的数组,它的特点是写加锁读不加锁,了解过ConcurrentHashMap的原理之后,再理解它的原理就比较简单了,来看看两个关键方法:

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();
}
}

public E get(int index) {
return (E)(getArray()[index]);
}

final Object[] getArray() {
return array;
}
从代码中可以看到,在往数组中添加元素时,把整个数组拷贝一份把数据插入到新数组中,然后用新数组代替老数组,这样保证多个线程不会再同一个时间点读到不一致的数据,在插入时加了全局锁,所以多个线程不能同时插入数据,而读操作时完全没有锁的,这里面array时一个volatile变量,这点很关键,在插入操作的最后设置这个volatile变量,由volatile在JMM中的happens-before语义,已及hp的传递性,保证了写操作完成之后,写操作更新的数据对读线程时可见的。和ConcurrentHashMap一样,CopyOnWriteArrayList也只能保证弱一致性。由于CopyOnWriteArrayList写操作要拷贝整个数组,所以整个操作对时间的消耗和对GC产生的压力都是比较可观的,而读操作由于无锁,所以读操作比较高效而且读线程之间不会发生阻塞,所以这个结构适用于读操作远远多于写操作的场景。

CopyOnWriteArraySet完全时基于CopyOnWriteArrayList来实现的,这里不再赘述。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: