CopyOnWriteArrayList抛出CurrentModificationException

时间:2009-10-06 19:16:40

标签: java multithreading exception collections

当我遍历列表时偶尔会得到ConcurrentModificationException。谷歌搜索告诉我,这可能是因为我在迭代它时在另一个线程中改变该列表并且为了使这个问题消失我应该使用java.util.concurrent.CopyOnWriteArrayList ....

......除了我已经是。

显然,我正在做某事真的愚蠢。

是否有人了解如何诱使CopyOnWriteArrayList抛出ConcurrentModificationException?如果重要,我正在使用Java 5.

编辑:由于我使用的mutators可能很重要,我正在以两种方式修改此列表:

  • 在前面添加元素。 (list.add(0, newElement);
  • 使用subList让较旧的项目从后面掉下来。 (list = list.subList(0, MAX_LIST_SIZE);

那些举起红旗吗?如果是这样,为什么?我的理解是,因为这些操作首先复制了这个东西,所以任何现有的迭代器都会指向未经修改的原始文件,因此不关心。我的知识是否有漏洞?

编辑2:导致问题的确切代码仍然有点模糊,但我至少可以发布我看到的异常:


java.util.ConcurrentModificationException
    at java.util.concurrent.CopyOnWriteArrayList$COWSubList.checkForComodification(Unknown Source)
    at java.util.concurrent.CopyOnWriteArrayList$COWSubList.iterator(Unknown Source)
    at....

...它指向我的代码中的for-each循环实例化。

COWSubList似乎意味着我对subList的调用是我问题的根源;我还是想明白为什么。

编辑3: * facepalm *

CopyOnWriteArrayList.subList()返回List a CopyOnWriteArrayList。它返回的清单没有提供任何COWAL保护的隐含义务。这使得像这样使用subList()来删除元素一个非常糟糕的主意。

不确定这是否是我的罪魁祸首,但它是可疑的,无论如何都需要纠正。

2 个答案:

答案 0 :(得分:17)

如果包含列表从其下面更改,则CopyOnWriteArrayList.subLists抛出ConcurrentModificationExceptions:

public class ListTest {

  private static List<int[]> intList;

  public static void main (String[] args) {
    CopyOnWriteArrayList<Integer> cowal = new CopyOnWriteArrayList<Integer>();
    cowal.add(1);
    cowal.add(2);
    cowal.add(3);

    List<Integer> sub = cowal.subList(1, 2);
    cowal.add(4);
    sub.get(0); //throws ConcurrentModificationException
  }
}

答案 1 :(得分:-1)

Sbodd有正确答案,但听起来好像使用CopyOnWriteArrayList而不是ArrayList只是试图掩盖错误。真正的问题是尝试在迭代它时修改基础列表。您需要在代码中找到您正在访问它的位置并删除该用法或解决它。