juc包中有两个关于写时复制的类
- CopyOnWriteArrayList
- CopyOnWriteArraySet
概念:顾名思义,写的时候,对数组进行复制。
适用场景:读多写少,大多数线程都是读请求,可以显著提高线程操作的效率,在读请求明显多于写请求的场景下,用于替换读写锁。
1 CopyOnWriteArrayList部分源码
数组是用volatile进行修饰的,关于volatile的相关说明,可以看我的这篇线程安全之可见性,volatile可以保证修改完的变量对其它线程立即可见。
/** The lock protecting all mutators */
final transient ReentrantLock lock = new ReentrantLock();
/** The array, accessed only via getArray/setArray. */
private transient volatile Object[] array;
1.1 写操作源码
public E set(int index, E element) {
final ReentrantLock lock = this.lock; //需要一把锁,防止多个线程对数组副本进行同时写
lock.lock();
try {
Object[] elements = getArray();
E oldValue = get(elements, index);
if (oldValue != element) {
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len); //创建数组副本
newElements[index] = element; //更新副本数组
setArray(newElements); //写完数组副本后,更新数组
} else {
// Not quite a no-op; ensures volatile write semantics
setArray(elements);
}
return oldValue;
} finally {
lock.unlock();
}
}
1.2 读操作源码
@SuppressWarnings("unchecked")
private E get(Object[] a, int index) {
return (E) a[index];
}
2 CopyOnWriteArraySet部分源码
封装了CopyOnWriteArrayList。
public CopyOnWriteArraySet() {
al = new CopyOnWriteArrayList<E>(); //实际上是封装了CopyOnWriteArrayList
}
/**
* Creates a set containing all of the elements of the specified
* collection.
*
* @param c the collection of elements to initially contain
* @throws NullPointerException if the specified collection is null
*/
public CopyOnWriteArraySet(Collection<? extends E> c) {
if (c.getClass() == CopyOnWriteArraySet.class) {
@SuppressWarnings("unchecked") CopyOnWriteArraySet<E> cc =
(CopyOnWriteArraySet<E>)c;
al = new CopyOnWriteArrayList<E>(cc.al);
}
else {
al = new CopyOnWriteArrayList<E>();
al.addAllAbsent(c);
}
}
参考文章
不了解这些“高级货”,活该你面试当炮灰。。。【石杉的架构笔记】
网易云课堂《Java高级开发工程师》
结语
本人所有博客仅用于学习记录,不做任何商业用途,如涉及侵权,还请联系删除,感谢阅读,欢迎留言,一起进步~