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

Java中有两种types的迭代器:失效保护和失效快速。

这是什么意思,是他们之间的区别?

他们之间有什么区别…

“故障安全”意味着:它不会失败。 严格地说,在Java中没有这样的事情作为故障安全迭代器。 正确的术语是“弱一致”。 javadoc说:

“大多数并发集合实现(包括大多数队列)也不同于通常的java.util惯例,因为它们的迭代器和Spliterator提供了弱一致性而不是快速失败遍历。

通常,弱一致性意味着如果一个集合与一个迭代同时被修改,那么迭代看到的保证就会变弱。 (细节将在每个并发集合类javadocs中指定。

“快速失败”是指: 可能会失败…并积极检查故障条件,以便可以完成损坏之前检测到故障条件(在可能的情况下1 )。 在Java中,通过抛出ConcurrentModificationExceptionexception快速迭代器失败。

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

…和它们与我们用于收集的迭代器不同。

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


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

  • 收集更新时,计数器递增。
  • 当一个Iterator被创build时,计数器的当前值被embedded在Iterator对象中。
  • Iterator操作被执行时,该方法比较两个计数器值,并且如果它们不同则抛出CME。

故障安全迭代器的实现通常是轻量级的。 它们通常依赖于特定列表实现的数据结构的属性。 没有一般的模式。 (阅读您感兴趣的特定集合类的源代码。)


1 – 骑车者认为,快速行为假定应用程序ID在同步和内存模型方面正确。 这意味着(例如)如果您迭代ArrayList没有正确的同步,最终的结果可能是一个损坏的列表结果。 “快速失败”机制可能会检测到并发修改(虽然这不是保证),但它不会检测到底层的损坏。 作为一个例子, Vector.iterator() javadoc说:

“迭代器的快速失败行为不能保证,一般来说,不可能在存在非同步并发修改的情况下做出任何硬性保证,快速失败的迭代器会尽可能抛出ConcurrentModificationException ,因此它会编写一个依赖于这个exception的程序是错误的,因为它的正确性:迭代器的快速失败行为应该只被用来检测错误。

他们是相当快速弱一致的types:

java.util迭代器抛出ConcurrentModificationException如果集合的方法修改了集合的方法(add / remove),而迭代

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

唯一的区别是自动防故障迭代器不会抛出任何exception,这与快速迭代器相反。

如果集合在结构上被修改,而一个线程正在迭代它。 这是因为他们对Collection的clone而不是原始的collection,所以他们被称为fail-safe迭代器。

CopyOnWriteArrayList的迭代器是故障安全迭代器的一个例子,ConcurrentHashMap写的迭代器keySet也是故障安全迭代器,永远不会抛出Java中的ConcurrentModificationExceptionexception。