侧边栏壁纸
博主头像
Terry

『LESSON 5』

  • 累计撰写 90 篇文章
  • 累计创建 21 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

关于Java中是否存在fail-safe

Terry
2020-10-31 / 0 评论 / 0 点赞 / 199 阅读 / 3,447 字 / 正在检测是否收录...

简述

我们在网上看到一些文章,提及到了HashMap迭代时候发生外部更改时,会抛异常,我们称之为fail-fast。但是ConcurrentHashMap却没有这种现象,文章会说这是fail-sale。而事实上,Java SE规范中没有使用fail-sale这一词,而是定义了四个不同的并行更改策略-fail-fastweakly consistentsnapshotundefined

fail-fast快速失败

java.util中大多数非并发包集合都具有快速失败迭代器。例如ArrayList

The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

意思是:

此类的迭代器和 listIterator 方法返回的迭代器是失速。 创建迭代器后,如果列表在结构上以迭代器本身的 remove 或 add 方法以外的方式更改,则迭代器将引发 ConcurrentModificationException。 因此,如果同时进行更改,迭代器将立即和手无常地引发异常,以避免在不可预想的未来时刻发生不可预想的行为的风险。

weakly consistent弱一致性

java.util.concurrent 中包含的大多数并发集合(如 ConcurrentHashMap)都是弱一致性的。

Most concurrent Collection implementations (including most Queues) also differ from the usual java.util conventions in that their Iterators and Spliterators provide weakly consistent rather than fast-fail traversal:
they may proceed concurrently with other operations
they will never throw ConcurrentModificationException
they are guaranteed to traverse elements as they existed upon construction exactly once, and may (but are not guaranteed to) reflect any modifications subsequent to construction.

意思是:

大多数并发集合实现(包括大多数 Queue)也与常规 java.util 规则不同,因为迭代器和拆分器提供弱一致性,而不是故障快速遍历。
可以与其他操作并行处理。
不要引发 ConcurrentModificationException。
它保证只遍历生成时存在的元素一次,并且可以(但不能保证)反映生成后更改。

snapshot快照

代表:CopyOnWriteArrayList

All mutative operations (add, set, and so on) are implemented by making a fresh copy of the underlying array.
The “snapshot” style iterator method uses a reference to the state of the array at the point that the iterator was created. This array never changes during the lifetime of the iterator, so interference is impossible and the iterator is guaranteed not to throw ConcurrentModificationException. The iterator will not reflect additions, removals, or changes to the list since the iterator was created.

意思是:

ArrayList 的线程安全变量,通过创建基础数组的新副本来实现所有传递操作(添加、设置等)。
"快照"样式迭代器方法使用对创建迭代器时数组状态的引用。 由于此数组永远不会在迭代器的生存期内更改,因此不可能进行干扰,并且迭代器保证不会引发 ConcurrentModificationException。 迭代器不会反映自创建迭代器以来对列表的添加、删除或更改。

undefined未定义

这策略是"无规定"(如果可以称之为策略)。 在迭代期间更新集合的结果未定义,并且可能发生不一致。 示例包括旧集合 Vector 和 HashTable,或返回 Enumeration 的方法,如 Vector.elements、Hashtable.elements 和 Hashtable.keys。

如果从 Vector.elements 方法迭代 Enumeration,则很容易发生不自然的行为,例如跳过元素、在迭代期间出现两次或发生意外异常。

顺便谈一下,当集合框架出现在 JDK 1.2 中时,Vector 和 Hashtable 被内置到实现新接口中。 例如,Vector 可以使用 Vector.elements 方法获取 Enumeration,也可以使用 Vector.iterator 方法获取 Iterator。 Iterator 具有 Enumeration 中未提供的故障快速策略。 Hashtable 也提供 Enumeration 和 Iterator,但只有 Iterator 具有失败快速策略。 有趣的是,哈希表的 Iterator 和 Enumeration作为同一类实现,并具有一个标志,用于确定它是 Iterator 还是枚举。

总结

可以看出,我们没有看到过fail-sale,其实是不存在的。作为对集合的更改策略,Java SE规范中没有使用fail-sale,所以我们使用fail-sale来定义其实不太可靠。如果要描述Java迭代器时,我们应该使用本文中提到的fail-fastweakly consistentsnapshotundefined这四中策略。

参考

There is no such thing as a fail-safe Iterator in Java
(翻訳)Javaにフェイルセーフなイテレータなんてものはない

0

评论区