TFdream/blog

JUC集合篇 - CopyOnWriteArraySet

TFdream opened this issue · 0 comments

CopyOnWriteArraySet介绍

它是线程安全的无序的集合,可以将它理解成线程安全的HashSet。

这里值得一提的是,CopyOnWriteArraySet和HashSet虽然都继承于共同的父类AbstractSet;但是,HashSet是通过“散列表 (HashMap)”实现的,而CopyOnWriteArraySet则是通过“动态数组CopyOnWriteArrayList”实现的,并不是散列表。

和CopyOnWriteArrayList类似,CopyOnWriteArraySet具有以下特性:

  • 它最适合于具有以下特征的应用程序:Set 大小通常保持很小,只读操作远多于可变操作,需要在遍历期间防止线程间的冲突。
  • 它是线程安全的。
  • 因为通常需要复制整个基础数组,所以可变操作(add()、set() 和 remove() 等等)的开销很大。
  • 迭代器支持hasNext(), next()等不可变操作,但不支持可变 remove()等 操作。
  • 使用迭代器进行遍历的速度很快,并且不会与其他线程发生冲突。在构造迭代器时,迭代器依赖于不变的数组快照。

官方原文如下:

A Set that uses an internal CopyOnWriteArrayList for all of its operations. Thus, it shares the same basic properties:

  • It is best suited for applications in which set sizes generally stay small, read-only operations vastly outnumber mutative operations, and you need to prevent interference among threads during traversal.
  • It is thread-safe.
  • Mutative operations (add, set, remove, etc.) are expensive since they usually entail copying the entire underlying array.
  • Iterators do not support the mutative remove operation.
  • Traversal via iterators is fast and cannot encounter interference from other threads. Iterators rely on unchanging snapshots of the array at the time the iterators were constructed.

CopyOnWriteArraySet原理和数据结构

CopyOnWriteArraySet的数据结构,如下图所示:
image

说明:

  • CopyOnWriteArraySet继承于AbstractSet,这就意味着它是一个集合。
  • CopyOnWriteArraySet包含CopyOnWriteArrayList对象,它是通过CopyOnWriteArrayList 实现的。而CopyOnWriteArrayList 本质是个动态数组队列,

所以CopyOnWriteArraySet相当于通过通过动态数组实现的“集合”! CopyOnWriteArrayList中允许有重复的元素;但是,CopyOnWriteArraySet是一个集合,所以它不能有重复集合。因此,CopyOnWriteArrayList额外提供了addIfAbsent()和addAllAbsent()这两个添加元素的API,通过这些API来添加元素时,只有当元素不存在时才执行添加操作!

至于CopyOnWriteArraySet的“线程安全”机制,和CopyOnWriteArrayList一样,是通过volatile和互斥锁来实现的。这个在前一章节介绍CopyOnWriteArrayList时数据结构时,已经进行了说明,这里就不再重复叙述了。