CopyOnWriteArrayList

聊聊并发-Java中的Copy-On-Write容器

爷,独闯天下 提交于 2020-04-14 16:38:46
【推荐阅读】微服务还能火多久?>>> Copy-On-Write简称COW,是一种用于程序设计中的优化策略。其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改,这是一种延时懒惰策略。从JDK1.5开始Java并发包里提供了两个使用CopyOnWrite机制实现的并发容器,它们是CopyOnWriteArrayList和CopyOnWriteArraySet。CopyOnWrite容器非常有用,可以在非常多的并发场景中使用到。 什么是CopyOnWrite容器 CopyOnWrite容器即写时复制的容器。通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。这样做的好处是我们可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器。 CopyOnWriteArrayList的实现原理 在使用CopyOnWriteArrayList之前,我们先阅读其源码了解下它是如何实现的。以下代码是向ArrayList里添加元素,可以发现在添加的时候是需要加锁的

CopyOnWriteArrayList详解

纵饮孤独 提交于 2019-12-06 09:28:42
CopyOnWriteArrayList是 ArrayList 的一个线程安全的变体,其中所有可变操作(add、set等等)都是通过对底层数组进行一次新的复制来实现的。 这一般需要很大的开销,但是当遍历操作的数量大大超过可变操作的数量时,这种方法可能比其他替代方法 更 有效。在不能或不想进行同步遍历,但又需要从并发线程中排除冲突时,它也很有用。“快照”风格的迭代器方法在创建迭代器时使用了对数组状态的引用。此数组在迭代器的生存期内不会更改,因此不可能发生冲突,并且迭代器保证不会抛出ConcurrentModificationException。创建迭代器以后,迭代器就不会反映列表的添加、移除或者更改。在迭代器上进行的元素更改操作(remove、set和add)不受支持。这些方法将抛出UnsupportedOperationException。 允许使用所有元素,包括null。 内存一致性效果:当存在其他并发 collection 时,将对象放入CopyOnWriteArrayList之前的线程中的操作 happen-before 随后通过另一线程从CopyOnWriteArrayList中访问或移除该元素的操作。 这种情况一般在多线程操作时,一个线程对list进行修改。一个线程对list进行fore时会出现java.util

How to sort CopyOnWriteArrayList

懵懂的女人 提交于 2019-12-03 14:22:42
问题 I want to sort CopyOnWriteArrayList. Currently it is throwing unsorted operation exception. import java.util.Collections; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; public class CopyOnWriteArrayListExample { public static void main(final String[] args) { List<String> list = new CopyOnWriteArrayList<>(); list.add("3"); list.add("2"); list.add("1"); Collections.sort(list); } } Exception in thread "main" java.lang.UnsupportedOperationException at java.util

Properly iterating over queues from ActiveMQ DestinationSource.getQueues response

余生颓废 提交于 2019-12-02 06:07:52
问题 For some reason in the following code, destinationSource.getQueues() is returning a CopyOnWriteArraySet instead of a simple Set . This is a problem because the for loop begins to process before the Set is full and due to the nature of CopyOnWriteArraySet it will only process the items in the Set before the loop. I know I can throw a Thread.sleep() in there but that doesn't fix the underlying problem. Is there any reason it would be returned as a CopyOnWriteArraySet instead of a Set ? Also is

Properly iterating over queues from ActiveMQ DestinationSource.getQueues response

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-02 03:23:17
For some reason in the following code, destinationSource.getQueues() is returning a CopyOnWriteArraySet instead of a simple Set . This is a problem because the for loop begins to process before the Set is full and due to the nature of CopyOnWriteArraySet it will only process the items in the Set before the loop. I know I can throw a Thread.sleep() in there but that doesn't fix the underlying problem. Is there any reason it would be returned as a CopyOnWriteArraySet instead of a Set ? Also is there any way to iterate over a CopyOnWriteArraySet to ensure all items would be covered, even ones

JDK容器学习之CopyOnWriteArrayList:线程安全保障机制

徘徊边缘 提交于 2019-11-27 18:40:41
JDK容器学习之CopyOnWriteArrayList 列表容器常见的有 ArrayList 和 LinkedList ,然而两者都是非线程安全的,若应用场景对线程安全有需求,则可以使用 CopyOnWriteArrayList 来代替传统的 Vector I. 存储结构 先看下类中定义的成员变量, 一个数组和一个锁 /** The lock protecting all mutators */ final transient ReentrantLock lock = new ReentrantLock(); /** The array, accessed only via getArray/setArray. */ private transient volatile Object[] array; array: 保存了列表中的数据 lock: 修改时加锁,用于保证线程安全 底层数据结构依然是数组,相交于 ArrayList 而言,少了一个表示数组长度的 size 变量,获取列表长度是通过下面的方法 public int size() { return getArray().length; } final Object[] getArray() { return array; } 留一个问题: 为什么获取链表的长度个ArrayList的使用姿势不同,这样做有什么好处 II.

JDK容器学习之List: CopyOnWriteArrayList,ArrayList,LinkedList对比

£可爱£侵袭症+ 提交于 2019-11-27 04:12:14
列表 List, ArrayList, LinkedList, CopyOnWriteArrayList, Vector 简述 1. 列表划分为线程安全和线程非安全两类 线程安全: Vector , CopyOnWriteArrayList , Collections.synchronizedList() 线程非安全: ArrayList , LinkedList 2. 底层存储 数组: ArrayList Vecotr CopyOnWriteArrayList 双向链表: LinkedList 通过三个添加元素的过程图,来看数据结构 ArrayList,Vector : 底层存储为数组 LinkedList : 底层存储为双向链表 CopyArrayList :底层存储为数组 3. 使用场景和说明 ArrayList 底层为数组,适合随机访问 删除不会引起数组容量变小 动态插入可能涉及到数组长度重新分配 为避免频繁的数组扩容,可设置一个合适的初始容量 不适用于频繁的在数组中间进行插入删除的场景 LinkedList 底层为双向链表,适合频繁删除新增的场景 随机访问不友好,需要遍历 Vector 线程安全 所有的方法都加锁,导致性能较差 CopyOnWriteArrayList 线程安全 读方法不加锁;修改方法加锁,一次只能一个写线程访问 修改时,会拷贝一份内容出来