什么是Java中的故障安全和故障快速迭代器


Answers:


84

他们之间有什么区别...

“故障安全”(在工程中)表示某些故障不会造成或只造成最小的损坏。严格地说,有没有这样的事情在Java中的故障安全迭代器。如果迭代器失败(通常为“失败”),则可能会发生损坏。

我怀疑您实际上是在说“弱一致性”迭代器。Javadoc说:

“大多数并发Collection实现(包括大多数Queue)也与通常的java.util约定不同,因为它们的Iterator和Spliterator提供了弱一致性而不是快速失败遍历。”

通常,弱一致性意味着如果在迭代过程中同时修改集合,则对迭代结果的保证就较弱。(详细信息将在每个并发集合类javadocs中指定。)

“快速失败”(在系统设计中)是指积极检查故障状况,以便在可能造成太多损坏之前(在可能的情况下为1)检测到故障状况。在Java中,快速失败的迭代器会因抛出失败ConcurrentModificationException

“快速失败”和“弱一致性”的替代是语义,其中迭代无法预测地失败。例如,有时会给出错误的答案或引发意外的异常。(这是Enumeration早期Java版本中API 的一些标准实现的行为。)

...并且它们不同于我们用于收集的迭代器。

否。这些是由标准Collection类型实现的迭代器的属性。也就是说,当针对同步和Java内存模型1正确使用它们时,它们要么是“快速失败”,要么是“弱一致性” 。


快速失败迭代器通常使用volatile收集对象上的计数器实现。

  • 更新集合时,计数器会增加。
  • Iterator创建an时,计数器的当前值将嵌入到Iterator对象中。
  • Iterator执行操作,该方法比较两个计数器值和抛出一个CME如果它们是不同的。

相反,弱一致性迭代器通常是轻量级的,并利用每个并发集合的内部数据结构的属性。没有一般模式。如果您有兴趣,请阅读不同集合类的源代码。


1-失败的原因是,快速失败行为假设应用程序ID关于同步和内存模型正确无误。这意味着(例如)如果您在ArrayList没有正确同步的情况下进行迭代,则结果可能是损坏的列表结果。“快速失败”机制可能会检测到并发修改(尽管不能保证),但不会检测到潜在的损坏。例如,javadoc for这样Vector.iterator()说:

“不能保证迭代器的快速失败行为,因为通常来说,在存在不同步的并发修改的情况下,不可能做出任何严格的保证。快速失败迭代器会ConcurrentModificationException尽力而为。因此,编写依赖于此异常的程序的正确性是错误的:迭代器的快速失败行为仅应用于检测错误。”


也许无关紧要,但也可以补充这个问题。例如,CoW使用的快照样式如何?更具体地说,我还不太了解CoW迭代器在“永不”上进行迭代的基础数组(或快照)如何看到其他线程所做的任何更改,因为我们仍然可以调用setArray任何修改。
stdout

我认为谈论弱一致性迭代器的实现超出了本问答的范围。
Stephen C

42

它们是快速失败不一致的类型:

如果在迭代时通过集合的方法(添加/删除)修改了集合,则从java.util包引发的ConcurrentModificationException迭代器

java.util.concurrent程序包中的迭代器通常在快照上进行迭代并允许并发修改,但在创建迭代器后可能无法反映集合更新。


迭代器是快速失败而枚举是安全的示例
Ajay Sharma 2015年

5
@AjaySharma-在两个方面不正确。1)无论是IteratorEnumeration指定的行为,快速失败或故障安全。指定行为的是特定的实现(即返回这些对象的特定的collection iterator()/ elements()etc方法)。2)典型的枚举实现既不是快速失败也不是安全失败的
斯蒂芬·C

22

唯一的区别是,与故障快速迭代器相反,故障保护迭代器不会引发任何异常。

如果在一个线程对其进行迭代时对Collection进行了结构上的修改。这是因为它们在Collection的克隆上而不是原始collection上工作,这就是为什么将它们称为故障保护迭代器。

CopyOnWriteArrayList的迭代器是故障安全迭代器的示例,而且ConcurrentHashMap keySet编写的迭代器也是故障安全迭代器,在Java中从不抛出ConcurrentModificationException。


我没有看到ConcurrentHashMap的迭代器工作的clone().. :(有些时候,它会反映一些更新的同时,迭代..
Kanagavelu Sugumar

0

这种情况与“并发处理”有关,意味着有更多的用户访问同一资源。在这种情况下,一个用户尝试修改导致“ ConcurrentProcessingException”的资源,因为在这种情况下,其他用户将获得不正确的数据。这两种类型都与这种情况有关。

简单来说

不及格:

  • 如果发生结构性修改(添加,更新,删除),则迭代器立即引发ConcurrentModificationException。
  • 示例:ArrayList,HashMap,TreeSet

故障安全:

  • 在这里,迭代器不会引发任何异常,因为它们对集合的副本(而不是原始副本)进行操作。因此,它们是故障安全的迭代器。
  • 示例:CopyOnWriteArrayList,ConcurrentHashMap
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.