CopyOnWriteArrayList适合什么场景? [重复]

问题描述 投票:0回答:2

我正在学习 CopyOnWriteArrayList 类。

  • 复制新数组的目的是什么?
  • 是否是为了其他线程读取数组?

所以如果一个系统并发度很高,并且大部分线程的动作都是读而不是写,那么最好使用

CopyOnWriteArrayList

java collections
2个回答
104
投票

如本链接所述:

CopyOnWriteArrayList 是 Java 5 并发 API 中引入的并发 Collection 类,以及 Java 中流行的表兄弟

ConcurrentHashMap
CopyOnWriteArrayList
实现了像
ArrayList
Vector
LinkedList
一样的 List 接口,但它是一个线程安全集合,并且它实现线程安全的方式与 Vector 或其他线程安全集合类略有不同。

顾名思义,

CopyOnWriteArrayList
使用每个突变操作创建底层 ArrayList 的副本,例如添加或设置。通常
CopyOnWriteArrayList
非常昂贵,因为它涉及每次写入操作的昂贵的数组复制,但是 如果您有一个迭代次数超过突变的列表,那么它会非常有效 例如你主要需要迭代 ArrayList 并且不要经常修改它。

CopyOnWriteArrayList

 的迭代器是故障安全的,即使在迭代开始后底层 CopyOnWriteArrayList 被修改,也不会抛出 
ConcurrentModificationException
,因为 Iterator 是在 ArrayList 的单独副本上操作。因此,迭代器无法使用 CopyOnWriteArrayList 上进行的所有更新。

要获取最新版本,请重新阅读

list.iterator();


话虽这么说,大量更新此集合会降低性能。如果您尝试对

CopyOnWriteArrayList

 进行排序,您将看到列表抛出 
UnsupportedOperationException
(排序调用在集合上设置 N 次)。仅当您的读取次数超过 90% 以上时才应使用此功能。


29
投票
应对新数组的目的是什么?

复制底层数组可以保证数据结构的任何迭代都是安全的,因为迭代是在数据的本质上不可变的“快照”上发生的。

是否是为了其他线程读取数组?

有点。更具体地说,每个线程都能够安全地迭代数组,而不必担心

ConcurrentModificationException

 或其他未知/未定义的行为。

所以如果系统并发度较高,并且线程的大部分动作都是读而不是写,那么最好使用CopyOnWriteArrayList。我说得对吗?

不。仅当大多数线程的操作都是对列表的迭代时。如果大多数活动都是基于随机访问的读取,则

ReadWriteLock

 可能会更好。

来自

CopyOnWriteArrayList

的javadoc

这通常成本太高,但当

遍历 操作远远超过突变时,可能比替代方案更有效,并且当您不能或不想同步 遍历 但需要排除并发线程之间的干扰时,这很有用。

© www.soinside.com 2019 - 2024. All rights reserved.