[英]STL-like Java Red-black tree / TreeSet/Map and linked lists with non fail-fast/safe iterators
[英]What are fail-safe & fail-fast Iterators in Java
Java 中有两种类型的迭代器:fail-safe 和 fail-fast。
这是什么意思,它们之间有什么区别?
它们之间有什么区别...
“故障安全”(在工程中)意味着某些故障不会造成损坏或造成最小损坏。 严格来说,Java 中没有故障安全迭代器这样的东西。 如果迭代器失败(在正常意义上的“失败”),您可以预期会发生损坏。
我怀疑您实际上是指“弱一致性”迭代器。 javadoc 说:
“大多数并发集合实现(包括大多数队列)也不同于通常的 java.util 约定,因为它们的迭代器和拆分器提供弱一致性而不是快速失败遍历。”
通常,弱一致性意味着如果集合在迭代的同时被修改,则迭代所看到的内容的保证较弱。 (详细信息将在每个并发集合类 javadocs 中指定。)
“Fail-fast”(在系统设计中)意味着积极检查故障情况,以便在造成过多损坏之前检测到故障情况(如果可能1 )。 在 Java 中,快速失败的迭代器通过抛出ConcurrentModificationException
失败。
“快速失败”和“弱一致性”的替代方案是语义,其中迭代失败不可预测; 例如,有时会给出错误的答案或抛出意外的异常。 (这是 Java 早期版本中Enumeration
API 的一些标准实现的行为。)
...它们与我们用于收集的迭代器不同吗?
不。这些是由标准集合类型实现的迭代器的属性; 即它们要么是“快速失败”,要么是“弱一致性”......当正确使用同步和 Java 内存模型1 时。
快速失败迭代器通常使用集合对象上的volatile
计数器来实现。
Iterator
,计数器的当前值嵌入在Iterator
对象中。Iterator
操作时,该方法比较两个计数器值,如果它们不同,则抛出 CME。相比之下,弱一致性迭代器通常是轻量级的,并且利用了每个并发集合的内部数据结构的特性。 没有通用的模式。 如果您有兴趣,请阅读不同集合类的源代码。
1 - 骑手是快速失败行为假设应用程序 id 在同步和内存模型方面是正确的。 这意味着(例如)如果在没有适当同步的情况下迭代ArrayList
,结果可能是损坏的列表结果。 “快速失败”机制可能会检测到并发修改(尽管不能保证),但它不会检测到潜在的损坏。 例如, Vector.iterator()
javadoc是Vector.iterator()
说的:
“无法保证迭代器的快速失败行为,因为一般来说,在存在未同步的并发修改的情况下不可能做出任何硬保证。快速失败的迭代器在尽力而为的基础上抛出
ConcurrentModificationException
。因此,它会编写一个依赖这个异常来保证其正确性的程序是错误的:迭代器的快速失败行为应该只用于检测错误。”
它们是相当快速且弱一致的类型:
如果在迭代时集合的方法(添加/删除)修改了集合,则java.util
包中的迭代器会抛出ConcurrentModificationException
java.util.concurrent
包中的迭代器通常迭代快照并允许并发修改,但在创建迭代器后可能不会反映集合更新。
唯一的区别是故障安全迭代器不会抛出任何异常,这与故障快速迭代器相反。
如果在一个线程迭代它时在结构上修改了 Collection。 这是因为它们处理的是 Collection 的克隆而不是原始集合,这就是它们被称为故障安全迭代器的原因。
CopyOnWriteArrayList 的迭代器是故障安全迭代器的一个例子,由 ConcurrentHashMap keySet 编写的迭代器也是故障安全迭代器,在 Java 中从不抛出 ConcurrentModificationException。
此场景与“并发处理”相关,意味着有多个用户访问同一资源。 在这种情况下,其中一个用户尝试修改导致“ConcurrentProcessingException”的资源,因为在这种情况下其他用户获得了不正确的数据。 这两种类型都与这种情况有关。
简单来说,
快速失败:
故障安全:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.