所有分类
  • 所有分类
  • 未分类

Java之List–CopyOnWriteArrayList的原理

简介

本文介绍Java的CopyOnWriteArrayList的原理。

CopyOnWriteArrayList是JUC的一个并发容器,它是个线程安全的ArrayList。

读操作无锁,写操作则通过创建底层数组的新副本来实现,是一种读写分离的并发策略,我们也可以称这种容器为”写时复制器”,JUC中类似的容器还有CopyOnWriteSet(底层是基于CopyOnWriteArrayList实现)。

Write的时候总是要Copy(将原来array复制到新的array,修改后,将引用指向新数组)。任何可变的操作(add、set、remove等)都通过ReentrantLock 控制并发。

优缺点

优点

  1. 读操作性能很高
    1. 因为读操作无需任何同步措施,适用于读多写少的并发场景。
  2. 不会抛出ConcurrentModificationException异常
    1. list在遍历时,若中途有别的线程对list容器进行修改,则会抛出ConcurrentModificationException异常。而CopyOnWriteArrayList由于其”读写分离”的思想,遍历和修改操作分别作用在不同的list容器,所以在使用迭代器进行遍历时候,也就不会抛出ConcurrentModificationException异常了

缺点

  1. 内存占用大
    1. 每次写操作都将原容器拷贝一份,数据量大时,对内存压力较大,可能会引起频繁GC;
  2. 无法保证实时性
    1. Vector对于读写操作均加锁同步,可以保证读和写的强一致性
    2. CopyOnWriteArrayList写和读分别作用在新老不同容器上,在写操作执行过程中,读不会阻塞但读取到的却是老容器的数据。
  3. 大量写操作性能极差

功能的限制

迭代器没有remove功能

CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
 
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()) {
	String next = iterator.next();
	iterator.remove();
}

结果

Exception in thread "main" java.lang.UnsupportedOperationException
	at java.util.concurrent.CopyOnWriteArrayList$COWIterator.remove(CopyOnWriteArrayList.java:1178)
	at ConcurrentSet.main(ConcurrentSet.java:47)

不支持Collections.sort(xx, yy)

会报异常:java.lang.UnsupportedOperationException

解决方案

List temp = Arrays.asList(copyOnWriteArrayList.toArray());
Collections.sort(temp);
copyOnwriteArrayList.clear();
copyOnWriteArrayList.addAll(temp);
0

评论0

请先

显示验证码
没有账号?注册  忘记密码?

社交账号快速登录