【问题标题】:Cannot understand this comment about fail-fast无法理解有关快速失败的评论
【发布时间】:2012-08-22 03:33:42
【问题描述】:

在 JDK 1.6 的 HashSet.java 中,有一些关于 HashSet 迭代器的 fail-fast 属性的 cmets。

这个类的迭代器方法返回的迭代器是快速失败的:如果集合在迭代器创建后的任何时候被修改,除了通过迭代器自己的删除方法之外,迭代器抛出一个 ConcurrentModificationException。因此,面对并发修改,迭代器会快速而干净地失败,而不是在未来不确定的时间冒任意的、非确定性的行为。

我可以理解上面的段落,因为它非常简单明了,但我无法理解下面的段落。如果我有一些简单的例子表明快速失败的迭代器甚至会失败,我可能会理解。

请注意,无法保证迭代器的快速失败行为,因为一般来说,在存在不同步的并发修改的情况下无法做出任何硬保证。快速失败的迭代器会尽最大努力抛出 ConcurrentModificationException。因此,编写一个依赖此异常的正确性的程序是错误的:迭代器的快速失败行为应仅用于检测错误。

【问题讨论】:

  • 它基本上是在说,不要依赖 Java 肯定会让你知道你在滥用迭代器。简而言之,您不能在迭代列表时修改它。

标签: java iterator hashset fail-fast


【解决方案1】:

编辑:对不起,我使用了一个列表,但这是相同的想法。这是关于迭代器,而不是它背后的集合。

EDIT2:这也更有可能发生在多线程环境中,您有两个线程,一个读取,一个写入。当您编码时,这些更难看到。要解决这些问题,您需要在列表上实施读/写锁以避免这种情况。

这是注释的代码示例:

Iterator itr = myList.iterator();

while(itr.hasNext())
{
    Object o = itr.next();

    if(o meets some condition)
    { 
        //YOURE MODIFYING THE LIST
        myList.remove(o);
    }
}

规范说的是你不能依赖这样的代码:

while(itr.hasNext())
{
     Object o = itr.next();

     try
     {
         if(o meets some condition)
            myList.remove(o);
     }
     catch(ConcurrentModificationException e)
     {
         //Whoops I abused my iterator. Do something else.
     }
}

相反,您可能应该将内容添加到新列表,然后将 myList 引用切换到刚刚创建的引用。这能说明情况吗?

【讨论】:

    【解决方案2】:

    第二段背后的想法是防止你写这样的代码:

    boolean ok = false;
    do {
        try {
            doTheModification();
            ok = true;
        } catch {
            // Consurrent modification - retry
        }
    } while (!ok);
    

    虽然这不是一个好的开始代码,但注释指出此代码无效(与次优相反)。他们说异常可能根本不会发生,所以上面的循环可能会默默地产生失败。

    【讨论】:

    • 这是一个非常简洁的示例,说明如果您有多个线程在同一个列表上工作,您可以(天真和错误地)编写什么代码。相反,您想使用 Java 语言的读/写锁。不依赖 ConcurrentModificationException。
    猜你喜欢
    • 2015-05-16
    • 2012-02-06
    • 2013-05-26
    • 2013-02-07
    • 1970-01-01
    • 2022-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多