在JDK1.6中的HashSet.java中,有一些关于HashSet迭代器的快速失败特性的注释。
这个类的迭代器方法返回的迭代器是快速失败的:如果在迭代器创建后的任何时候对集合进行了修改,那么除了通过迭代器自己的remove方法之外,其他任何方式都会抛出一个ConcurrentModificationException。因此,在并发修改的情况下,迭代器会迅速而干净地失败,而不是在未来某个未定的时间冒着任意的、不确定的行为的风险。
我能理解上面的段落,因为它非常简单和清晰,但我不能理解下面的段落。如果我有一些简单的例子,说明一个快速失败的迭代器甚至会失败,我可能会理解它。
请注意,迭代器的快速失败行为不能保证,一般来说,在不同步并发修改的情况下不可能提供任何硬的保证。快速失败的迭代器在最大努力的基础上将ConcurrentModificationException抛出。因此,编写一个依赖于此异常的程序是错误的:迭代器的快速失败行为应该只用于检测bug。
发布于 2012-08-27 16:10:14
编辑:对不起,我用了一个列表,但这是一个相同的想法。这是关于迭代器的,而不是它背后的集合。
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引用切换到刚刚创建的引用。这能解释情况吗?
发布于 2012-08-27 16:11:45
第二段背后的想法是阻止您编写这样的代码:
boolean ok = false;
do {
try {
doTheModification();
ok = true;
} catch {
// Consurrent modification - retry
}
} while (!ok);虽然这不是一个好的代码开始,但注释指出,该代码是无效的(相对于,例如,次优)。他们说,异常可能根本不会发生,所以上面的循环可能会默默地产生失败。
https://stackoverflow.com/questions/12145493
复制相似问题