Java 无法理解有关fail fast的此评论

Java 无法理解有关fail fast的此评论,java,iterator,hashset,fail-fast,Java,Iterator,Hashset,Fail Fast,在JDK1.6中的HashSet.java中,有一些关于HashSet迭代器的fail-fast属性的注释 这个类的迭代器方法返回的迭代器是快速失败的:如果在迭代器创建后的任何时候,以任何方式(除了通过迭代器自己的remove方法)修改集合,迭代器将抛出ConcurrentModificationException。因此,在面对并发修改时,迭代器会快速、干净地失败,而不是在将来的不确定时间冒着任意、不确定行为的风险 我能理解上面的段落,因为它非常简单明了,但我不能理解下面的段落。如果我有一些简单

在JDK1.6中的HashSet.java中,有一些关于HashSet迭代器的fail-fast属性的注释

这个类的迭代器方法返回的迭代器是快速失败的:如果在迭代器创建后的任何时候,以任何方式(除了通过迭代器自己的remove方法)修改集合,迭代器将抛出ConcurrentModificationException。因此,在面对并发修改时,迭代器会快速、干净地失败,而不是在将来的不确定时间冒着任意、不确定行为的风险

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

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


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

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.
     }
}
boolean ok = false;
do {
    try {
        doTheModification();
        ok = true;
    } catch {
        // Consurrent modification - retry
    }
} while (!ok);

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

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

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.
     }
}
boolean ok = false;
do {
    try {
        doTheModification();
        ok = true;
    } catch {
        // Consurrent modification - retry
    }
} while (!ok);

相反,您可能应该向新列表中添加内容,然后将myList引用切换到刚刚创建的引用。这就解释了这种情况吗?

第二段的思想是防止您编写这样的代码:

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.
     }
}
boolean ok = false;
do {
    try {
        doTheModification();
        ok = true;
    } catch {
        // Consurrent modification - retry
    }
} while (!ok);

虽然这不是一个好的开始代码,但注释指出该代码无效,而不是次优代码。他们说异常可能根本就不会出现,因此上面的循环可能会无声地产生故障。

第二段的思想是防止您编写如下代码:

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.
     }
}
boolean ok = false;
do {
    try {
        doTheModification();
        ok = true;
    } catch {
        // Consurrent modification - retry
    }
} while (!ok);

虽然这不是一个好的开始代码,但注释指出该代码无效,而不是次优代码。他们说异常可能根本就不会出现,因此上面的循环可能会无声地产生故障。

基本上是说,不要依赖Java来明确地让您知道您正在滥用迭代器。简单地说,你不能在遍历列表时修改它,它基本上是说,不要依赖Java来明确地让你知道你在滥用迭代器。简单地说,你不能在遍历列表时修改它。这是一个非常简洁的例子,说明了如果有多个线程在同一个列表上工作,你可能会天真地或错误地编写代码。相反,您希望使用Java语言读/写锁。不要依赖ConcurrentModificationException。这是一个非常简洁的示例,说明了如果有多个线程在同一个列表上工作,您可能会天真地或错误地编写代码。相反,您希望使用Java语言读/写锁。不依赖ConcurrentModificationException。