【问题标题】:What are fail-safe & fail-fast Iterators in Java什么是 Java 中的故障安全和故障快速迭代器
【发布时间】:2013-06-26 23:26:24
【问题描述】:

Java 中有两种类型的迭代器:fail-safe 和 fail-fast。

这是什么意思,它们之间有什么区别?

【问题讨论】:

标签: java iterator terminology


【解决方案1】:

唯一的区别是故障安全迭代器不抛出任何异常,与故障快速迭代器相反。

如果 Collection 在结构上被修改,而一个线程正在对其进行迭代。这是因为它们在 Collection 的克隆而不是原始集合上工作,这就是为什么它们被称为故障安全迭代器。

CopyOnWriteArrayList 的迭代器是故障安全迭代器的示例,也是由 ConcurrentHashMap 编写的迭代器 keySet 也是故障安全迭代器,在 Java 中永远不会抛出 ConcurrentModificationException。

【讨论】:

  • 我没有看到 ConcurrentHashMap 迭代器正在处理 clone() .. :( 有时它会在迭代时反映一些更新..
【解决方案2】:

它们是快速失败和弱一致类型:

如果集合在迭代时被集合的方法(添加/删除)修改,则来自 java.util 包的迭代器会抛出 ConcurrentModificationException

java.util.concurrent 包中的迭代器通常迭代快照并允许并发修改,但在创建迭代器后可能不会反映集合更新。

【讨论】:

  • 迭代器是快速失败的例子,而枚举是失败安全的
  • @AjaySharma - 在两个方面不正确。 1) Iterator 或 Enumeration 均未将行为指定为快速故障或故障安全。指定行为的是特定的实现(即返回这些对象的特定集合 iterator() / elements() 等方法)。 2) 典型的枚举实现既不是快速故障也不是故障安全。
【解决方案3】:

它们有什么区别...

“故障安全”(in engineering) 表示某些故障以不会造成损害或造成最小损害的方式发生。严格来说,在 Java 中不存在作为故障安全迭代器的东西。如果迭代器失败(通常意义上的“失败”),您可以预期会发生损坏。

我怀疑您实际上是指“弱一致”迭代器。 javadoc 说:

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

通常,弱一致性意味着如果集合与迭代同时被修改,则迭代所看到的内容的保证会更弱。 (详细信息将在每个并发集合类 javadocs 中指定。)

“Fail-fast” (in systems design) 表示积极检查故障情况,以便在造成过多损坏之前(在可能的情况下1)检测到故障情况。在 Java 中,快速失败的迭代器通过抛出 ConcurrentModificationException 失败。

“快速失败”和“弱一致”的替代方案是迭代失败不可预测的语义;例如有时给出错误的答案或抛出意外的异常。 (这是早期 Java 版本中 Enumeration API 的一些标准实现的行为。)

...它们与我们用于收集的迭代器有什么不同。

没有。这些是标准集合类型实现的迭代器的属性;即,它们要么是“快速失败”,要么是“弱一致性”……当正确使用同步和 Java 内存模型时1。


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

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

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


1 - 快速失败的迭代器行为假设应用程序在同步和内存模型方面已正确实现。 (换句话说,应用程序是线程安全的。)例如,如果您在没有适当同步的情况下迭代ArrayList,“快速失败”机制应该检测到并发修改(尽管那不是t 保证),但可能无法防止由于应用程序的不安全行为而损坏列表。为了说明,Vector.iterator() 的 javadoc 表示:

“不能保证迭代器的快速失败行为,因为一般来说,在存在不同步的并发修改的情况下不可能做出任何硬保证。快速失败迭代器最好抛出ConcurrentModificationException -努力基础。因此,编写一个依赖此异常的正确性的程序是错误的:迭代器的快速失败行为应该仅用于检测错误。"

【讨论】:

    【解决方案4】:

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

    简单来说,

    快速失败:

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

    故障保护:

    • 这里的迭代器不会抛出任何异常,因为它们操作的是集合的克隆,而不是原始集合。因此,它们是故障安全迭代器。
    • 示例:CopyOnWriteArrayList、ConcurrentHashMap

    【讨论】:

      猜你喜欢
      • 2015-12-17
      • 1970-01-01
      • 2016-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-19
      • 2015-04-27
      相关资源
      最近更新 更多