Java---并发容器之CopyOnWriteArrayList

25 篇文章 0 订阅
11 篇文章 0 订阅

一.概述

ArrayList并不是线程安全的,在读线程在读取ArrayList的时候如果有写线程在写数据的时候,基于fast-fail机制(),会抛出ConcurrentModificationException异常,也就是说ArrayList并不是一个线程安全的容器,当然可以用Vector,或者使用Collections的静态方法将ArrayList包装成一个线程安全的类,但是这些方式都是采用Java关键字synchronzied对方法进行修饰,利用独占式锁来保证线程安全的。但是,由于独占式锁在同一时刻只有一个线程能够获取到对象监视器,很显然这种方式效率并不是太高。

Copy-On-Write简称COW,是一种用于程序设计中的优化策略。
其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改,这是一种延时懒惰策略
CopyOnWrite容器即写时复制的容器
通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。
这样做的好处是我们可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。
所以CopyOnWrite容器是一种读写分离的思想,读和写不同的容器、最终一致性 以及使用另外开辟空间的思路,来解决并发冲突的思想。

ps:fast-fail机制:Java集合(Collection)中的一种错误机制。 当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast机制。在调用next和remove方法时,都会执行checkForComodification。若"modCount 不等于 expectedModCount"。则抛出ConcurrentModificationException异常,产生fail-fast事件即,当多个线程对同一个集合进行操作的时候,某线程访问集合的过程中,该集合的内容被其他线程所改变(即其它线程通过add、remove、clear等方法,改变了modCount的值);这时,就会抛出ConcurrentModificationException异常,产生fail-fast事件。fail-fast解决办法:若在多线程环境下使用fail-fast机制的集合,建议使用“java.util.concurrent包下的类”去取代“java.util包下的类”。

它的思想和Git就很相似,即使在多个线程中被并发访问, CopyOnWriteArrayList 的读操作(比如 get())也不会阻塞其他操作;写操作则是通过复制一份,对复制版本进行操作,不会影响原来的数据。

CopyOnWrite并发容器用于读多写少的并发场景。比如白名单,黑名单等场景。

二.实现

很多时候,我们系统中处理的都是读多写少的并发场景。CopyOnWriterArrayList 允许并发的读,读操作是无锁的,性能较高。写操作的话,比如向容器增加一个元素,则首先将当前容器复制一份,然后在新副本上执行写操作,结束之后再将原容器的引用指向新容器。

二.优缺点

1.优点

  • 读操作性能很高,因为无需任何同步措施,比较适用于读多写少的并发场景;
  • 读写分离,遍历和修改操作分别作用在不同的 list容器。

2.缺点

  • 内存占用问题:因为CopyOnWrite的写时复制机制,所以在进行写操作的时候,内存里会同时驻扎两个对象的内存,旧的对象和新写入的对象(注意:在复制的时候只是复制容器里的引用,只是在写的时候会创建新对 象添加到新容器里,而旧容器的对象还在使用,所以有两份对象内存)。如果这些对象占用的内存比较大,比 如说200M左右,那么再写入100M数据进去,内存就会占用300M,那么这个时候很有可能造成频繁的minor GC和major GC
  • 数据一致性问题:CopyOnWrite容器只能保证数据的最终一致性,不能保证数据的实时一致性。所以如果你希望写入的的数据,马上能读到,请不要使用CopyOnWrite容器。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值