我正在使用Iterator处理一段代码,并在Windows上从IDE运行程序时在a行获得ConcurrentModificationException--
LinkedList ll =new LinkedList();
. . .
. . .
Iterator iter = ll.iterator();
int i=0;
while (iter.hasNext()) {
// GrammarSection agrammarSection = (GrammarSection) iter.next(); //a
String s1 = (String) iter.next();
ll.remove(i);
i++;
}
这是意料之中的,因为我在迭代时修改了列表,因此故障快速迭代器会引发并发修改异常。但是,当我使用 apache 服务器在 unix 中运行此代码时,迭代器的下一个方法不会引发任何异常。那么,并发修改异常是否取决于操作系统级别?
不,不应该。 无论如何,它应该崩溃。
我想在不同的 JVM 上可能会有所不同,但根据官方规范,链表上的迭代器应该是快速失败的。
操作系统与它无关。
我发现了问题可能是什么。当您的列表有 2 个元素时,hasNext()
返回 false
并且它无一例外地工作。如果列表有 3 个或更多元素,则会在任何地方抛出异常。因此,请确保您的列表具有正确数量的元素。
至于操作系统依赖性 - java代码不依赖于操作系统
无论如何 - 使用 iter.remove()
- 它将从基础列表中删除元素而不会导致异常。
您的方法的问题在于,您正在修改基础列表,而迭代器不知道该修改的任何内容。因此,您必须通过迭代器执行它。
那么,并发修改是否 异常取决于操作系统级别?
它确实有一些 JMV 依赖性,但不在您显示的代码中。
// LinkedLists have a member variable called modCount
// which is an integer which holds the count of modifications
// made on the list with methods like list.add() list.remove() etc.
LinkedList ll =new LinkedList();
. . .
. . .
// When the iterator is created here, it copies the current modCount
// of the LinkedList into a member of its own called expectedModCount
Iterator iter = ll.iterator();
int i= 0;
while (iter.hasNext()) {
// iter.next() calls a method called checkForComodification
// which throws a ConcurrentModificationException if the
// current modCount of the original LinkedList is different
// from the expectedModCount on this iterator
String s1 = (String) iter.next();
ll.remove(i);
i++;
}
当在不同的线程中访问和迭代列表而没有正确同步时,对LinkedList.modCount
所做的修改(调用 LinkedList.add
、 LinkedList.remove
等时)可能对执行迭代的线程不可见。所以一般来说,ConcurrentModificationException
不能保证被扔掉。但是在您展示的单线程代码中,应该没有可见性问题,如果在 ll.iterator()
之后成功调用ll.remove()
,则应始终抛出异常。
use iter.remove() ; not ll.remove(i)
如果使用迭代器 remove 函数,则不会得到并发修改异常。
但是,要回答您的问题;CME不应依赖于操作系统级别。你的代码一定还有其他一些问题,为什么它没有在 unix 中抛出 CME。
顺便说一句,该规范有以下评论
"请注意,迭代器的快速故障行为无法保证,因为一般来说,在存在不同步的并发修改的情况下,不可能做出任何硬保证。Fail-fast 迭代器会尽最大努力抛出 ConcurrentModificationException。因此,编写一个依赖于此异常的正确性的程序是错误的:迭代器的快速故障行为应该仅用于检测错误。