【问题标题】:FailSafe Feature故障保护功能
【发布时间】:2011-06-26 12:45:19
【问题描述】:

在问这个问题之前,我已经尝试了解(在 SOF 和其他一些网站上)故障安全功能。我知道 Java 集合迭代器是快速失败的,这基本上意味着一旦底层集合被结构性修改(即使是同一个线程),它们就会优雅地失败。我的问题是故障安全属性是否与迭代器的 remove() 或 add() 功能有关?在我的理解中,因为通过迭代器,您可以在迭代集合时(安全地)添加或删除,并且您不会得到并发异常(您在不使用它们的删除和添加功能的情况下这样做),因此使迭代器具有故障安全性。还是我完全搞错了?

谢谢!

【问题讨论】:

    标签: java iterator


    【解决方案1】:

    不完全是。据我了解,故障安全迭代器处理数据的快照,并保证在创建迭代器时所表示的集合的一致视图。 (有关此问题的更详细处理,请参阅this blog post)。此属性是保证 f.i.通过CopyOnWriteArrayList 的迭代器。它的迭代器不支持集合修改操作,它的 javadoc 进一步阐明了它们的行为:

    这个数组在 迭代器的生命周期,所以 干扰是不可能的,并且 迭代器保证不会抛出 并发修改异常。这 迭代器不会反映添加, 自删除或更改列表以来 创建了迭代器。 元素改变操作 迭代器本身(删除、设置和 不支持添加)。这些方法 抛出 UnsupportedOperationException。

    更新:

    在谈论故障安全性和故障稳定性时,将“故障”区分开来很重要。在迭代器的情况下,有不同的情况和危险。至于链接的文章,我会说作者首先通过实现迭代器来实现故障安全和故障快速迭代

    这种情况下的失败可以定义为迭代集合的并发修改。当集合被修改时,快速失败的方法将是停止迭代并让调用者知道更改的条件(通过CME 或通过其他方式)。

    在处理相同的用例和危险时,我们可以继续前进并考虑故障安全迭代。故障安全属性意味着迭代应尽可能长时间地遵守其合同(COWAS 的作者通过复制基础数据成功)。

    【讨论】:

    • 谢谢亚历克斯,我想我以前读过这个博客,但我无法回答我的问题,他创建了两个迭代器,一个有副本,另一个没有副本,然后说一个没有副本会抛出一个修改异常。我认为即使没有副本也可以进行故障保护,您只需要继续检查是否有任何修改。
    • 故障安全只是一个属性,他的实现通过提供一个副本来保证它。如果您可以通过其他方式保证故障安全,则取决于您。当您检查修改并发现该集合被修改时,您将如何保证此属性?顺便说一句,您是否阅读了该博客文章中对维基百科的引用?
    • 您说“故障安全迭代器处理数据快照并保证在创建迭代器时所表示的集合的一致视图”,这意味着您要么有故障安全迭代器,要么失败-fast,而这个link 帖子说两者并不相反。
    • @WReach 通过示例给出了很好的解释。我认为从迭代器中抽象出来并首先理解这两个属性会很有帮助。一般而言,什么是故障安全,什么是快速故障。然后转到迭代器。正如您从CopyOnWriteArrayList 的javadoc 中看到的,它抛出UnsupportedOperationException,这是“快速失败”行为的一个示例(通过抛出异常,它说:如果您通过迭代器集合修改它,那么您就是做错事)。这些性质并不相反。
    • @Alex,你是对的,一旦集合被修改,迭代器必须快速失败。也请评论我的最后一条评论。谢谢
    【解决方案2】:

    IteratorListIterator 在底层集合上的工作不会使迭代器无效。通过任何其他迭代器或集合本身进行的任何修改都会使某些集合的迭代器无效。有些集合是为并发访问而设计的,没有这个限制。

    【讨论】:

    • “不会失效”:我假设您的意思是“不会失效”?
    猜你喜欢
    • 2021-09-23
    • 2012-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-25
    • 1970-01-01
    • 2012-05-08
    • 2011-01-31
    相关资源
    最近更新 更多