CopyOnWriteArrayList 的行为
CopyOnWriteArrayList
的 Javadocs 说
ArrayList 的线程安全变体,其中所有可变操作 (添加、设置等)是通过制作新的副本来实现的 底层数组。
我现在很困惑其他线程何时会看到这个新副本中存在的更改?这是否意味着底层数组的副本数量等于集合的突变数量?如果不是这样,这些单独副本的更改何时传输到底层数组以便其他线程可以看到它们?
Javadocs of CopyOnWriteArrayList
says
A thread-safe variant of ArrayList in which all mutative operations
(add, set, and so on) are implemented by making a fresh copy of the
underlying array.
I am confused now when will other threads see changes present in this fresh copy? Does this mean there will be number of copies of the underlying array equal to the number of mutations of the collection? If not so when are the changes of these individual copies are transferred to underlying array so that other threads can see them?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这里的想法是,每当您向 CopyOnWriteArrayList 添加或删除时,底层数组基本上都会被复制并进行修改。
是的,对于每个更新 ArrayList 的线程,持有旧副本的所有其他线程本质上都会引用不同的数组
您当前正在查看的数组(假设您的迭代器)永远不会改变。当您从数组中读取时,您正在读取它,就像您开始读取时一样。如果另一个线程更改了 CopyOnWriteArrayList,您当前正在观察的数组将不会受到影响。
要获取最新版本,请执行新的读取操作,例如
list.iterator();
也就是说,大量更新此集合会降低性能。如果您尝试对 CopyOnWriteArrayList 进行排序,您将看到列表抛出 UsupportedOperationException(在集合上设置的排序调用 N 次)。仅当您执行 90% 以上的读取时才应使用此读取。
The idea here is that whenever you add or remove to the
CopyOnWriteArrayList
, the underlying array is basically copied with the modification.Yes, for every thread that updates the
ArrayList
all other threads holding an older copy will in essence be referencing a different array.An array you are looking at currently (lets say your iterator) will never change. When you read from an array you are reading it as it was when you started reading. If the
CopyOnWriteArrayList
changes by another thread, the array you're currently observing will not be effected.To get the most updated version do a new read like
list.iterator();
That being said, updating this collection alot will kill performance. If you tried to sort a
CopyOnWriteArrayList
you'll see the list throws anUsupportedOperationException
(the sort invokes set on the collection N times). You should only use this read when you are doing upwards of 90+% reads.写时复制数组列表的实现使用底层数组并使用 setter 和 getter 方法访问它。
因此,对于添加、设置操作,它会创建当前数组的副本(使用 getArray),然后添加元素并返回更新后的数组(使用 setArray)。
是的,在 add 或 set 方法之前访问 arraylist 的线程将拥有过时的数据副本(如果您可以处理某种程度的过时数据,这很好,因为 CopyOnWriteArrayList 的设计思想是遍历操作将超过添加或更新的数量操作)并且所有将创建迭代器或使用 get 操作的线程都将拥有 arrayList 的最新数据。
这里 getarray 将给出 arrayList 的最新状态。
The implementation for copy on write array list uses the underlying array and accesses it using the setter and getter methods.
So for add, set operations it creates copies of the current array (using getArray) and the adds the element and returns back the updated array (using setArray).
yes the threads that have accessed the arraylist before add or set methods will be having a stale copy of data (which is fine if you can handle some degree of stale data, as CopyOnWriteArrayList is designed with this idea that traversal operations will outnumber adding or update operations) and all the threads that will create an iterator or use get operation will have the latest data of the arrayList.
here getarray will give the latest state of the arrayList.