为什么迭代器被称为故障安全或快速故障?

Why iterators are called fail safe or fail fast?

为什么迭代器被称为 "fail-safe" 和 "fail-fast",即使 Iterator.remove() 在遍历 Collection 时没有抛出任何 ConcurrentModificationException(例如, HashMap) 使用 Iterator ?

使用 Iterator.remove() 不会抛出 ConcurrentModificationException,但如果 其他东西 (在另一个线程中)修改 Collection 支持Iterator在迭代过程中,然后它会。

来自 Java API 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.

同一文档的下一句准确解释了 fail-fast 在这种情况下的含义;再次,我添加的粗体强调:

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.

换句话说,如果另一个线程修改了集合,那么简单而安全的做法是以 ConcurrentModificationException 的形式导致故意的、明确的失败,而不是试图计算出一个非- 失败,即 故障安全 ,逻辑(例如通过 Iterator 显示修改,具体取决于该元素是否已经被迭代)可能很复杂并且容易出错。

顾名思义,快速失败迭代器一旦意识到自迭代开始以来 Collection 的结构已更改,就会失败。结构更改意味着在一个线程迭代该集合时从集合中添加、删除或更新任何元素。快速失败行为是通过保持修改计数来实现的,如果迭代线程意识到修改计数的变化,它会抛出 ConcurrentModificationException。

与快速失败迭代器相反,如果在结构上修改集合,则失败安全迭代器不会抛出任何异常 而一个线程正在迭代它,因为它们在 Collection 的克隆而不是原始集合上工作,这就是为什么它们被称为故障安全迭代器。 CopyOnWriteArrayList 的迭代器是故障安全迭代器的一个示例,由 ConcurrentHashMap keySet 编写的迭代器也是故障安全迭代器,从不在 Java.

中抛出 ConcurrentModificationException
  • 故障安全迭代器意味着它们不会抛出任何异常,即使集合是 迭代时修改。
  • 而快速失败迭代器抛出异常(ConcurrentModificationException)如果 集合在迭代时被修改。

我的回答包括两点。

  1. 对于标记为正确的答案,重要的是要补充一点,即 fail-fast 迭代器的行为并非 100% 可靠(API 文档说明了这一点)。 The docs say 它的行为在 best-effort 基础上,建议仅将其用于错误检测:

Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs

因此,您可能应该在编写代码时考虑到这种行为,但您肯定绝不能完全依赖它。

  1. 有一个很好的article。我知道写的比问的晚。但是,我发现了解所谓的 concurrent modification policy.
  2. 很有用

所以,有四个政策,其中没有fail-safe一个:

  1. Fail-fast
  2. 弱一致
  3. 快照
  4. 未定义

article 的结论是:

After all this, where does “fail-safe” come into the picture? Answer: it doesn’t. The words “fail-safe” are never used in the Java SE specifications that describe the concurrent modification policy of a collection. As such, there is no reliable, consistent definition of “fail-safe” for an Iterator. One can attempt to apply the general concept of “fail-safety” to an Iterator, but this is open to varying, misleading, and even contradictory interpretations.

Don’t use “fail-safe” to describe a Java Iterator. Instead, use one of the documented policies listed above.