抛出ConcurrentModificationException系统依赖

时间:2011-05-19 15:17:14

标签: java collections

我正在使用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++;
   }

这是预期的,因为我在迭代时修改列表,因此失败快速迭代器会抛出Concurrentmodification异常。但是,当我在unix中使用apache服务器运行此代码时,迭代器的下一个方法不会抛出任何异常。那么,并发修改例外是否依赖于操作系统级别?

4 个答案:

答案 0 :(得分:3)

不,不应该。无论如何它应该崩溃。

我想在不同的JVM上可能会有所不同,但根据official spec,链表上的迭代器应该是快速失败的。

操作系统与它无关。

答案 1 :(得分:1)

我发现了问题所在。当您的列表包含2个元素时,hasNext()会返回false,并且无异常。如果列表包含3个或更多元素,则会在任何地方抛出异常。因此,请确保您的列表中包含正确数量的元素。

至于操作系统依赖性 - java代码不依赖于操作系统

无论如何 - 使用iter.remove() - 它会从基础列表中删除元素而不会导致异常。

您的方法的问题是您正在修改基础列表,而迭代器不知道该修改的任何内容。所以你必须通过迭代器来实现它。

答案 2 :(得分:0)

使用iter.remove();不是ll.remove(i)

如果使用迭代器删除函数,则不会出现并发修改。

然而,要回答你的问题; CME不应该依赖于操作系统级别。您的代码必须存在其他问题,以确定它不会在unix中抛出CME。

顺便说一句,该规范有以下评论

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

答案 3 :(得分:0)

  

那么,并发修改   异常取决于操作系统级别?

它确实有一些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.addLinkedList.remove等被调用时)的修改可能对线程不可见做迭代。所以ConcurrentModificationException一般都不能保证被抛出。但是在您展示的单线程代码中,应该没有可见性问题,如果在ll.remove()之后成功调用ll.iterator(),则应始终抛出异常。