当程序中的所有方法同步时,我是否可能得到ConcurrentModificationException?

时间:2011-12-20 22:55:30

标签: java concurrency concurrentmodification

即使我使整个程序的所有方法都同步(包括静态方法和ConcurrentModificationException方法),我得到main

我没有隐藏的迭代器。

  1. 这怎么可能?!
  2. 这是什么意思?
  3. 我该如何解决?

7 个答案:

答案 0 :(得分:6)

  1. ConcurrentModificationException可能是由相同的线程在迭代时操纵集合引起的
  2. 这意味着在迭代它们时不要更改集合,除非通过Iterator.remove()ListIterator.add()方法
  3. 见2。

答案 1 :(得分:3)

当您在一个集合上进行迭代时会遇到此异常,在此期间您将从此集合中删除一个条目。

e.g。

Collection<Object> objects = new ArrayList<Objects>(Arrays.asList("a","b"));
for (Object o : objects) {
    objects.remove(o); //throws exception
}

您必须将要删除的内容添加到另一个集合中,并在完成对列表的迭代后删除它们。 否则,通过iterator()迭代对象集合,并在当前迭代器上调用remove()。

答案 2 :(得分:3)

ConcurrentModificationException与同步无关。

它与在迭代时修改集合有关。正如Lie Ryan指出的那样,完整的堆栈跟踪将帮助我们指出你是如何得到它的。

通常,为了解决这个问题,你不能在迭代它时修改集合本身。

答案 3 :(得分:3)

如果你运行

List<Object> list = new ArrayList<Object>();
for(Object obj : list)
    list.remove(obj);

你会得到一个编纂。在不使用适当的函数的情况下迭代它时,您无法更改集合。

可以使用以下方法解决此问题:

List<Object> list = new ArrayList<Object>();
for(Iterator<Object> itr = list.iterator(); itr.hasNext();)
    itr.remove();

答案 4 :(得分:3)

嗯,首先,如果你看到它,它是可能的:如果鸟书和鸟不同意,相信鸟。

现在,怎么会发生?很难说没有看到你的代码,但异常堆栈跟踪将指向它发生的地方;你怎么看周围的?

一般情况下,当你有明显的并发访问时,就会发生这种情况。当你找到它发生的地方时,问问自己什么线程可以到达那里。

答案 5 :(得分:1)

synchronized方法锁定正在运行的对象实例。

如果对象A和B访问同一个集合,那么A#doStuff和B#doStuff是否同步并不重要 - 它们仍然可以同时执行。

要锁定集合,您可能需要锁定集合本身:方法体中的synchronized(集合)或Java 5互斥体(更好)。

(即使在其他人指出的单个线程中你也可以拥有ConcurrentModificationException)。

答案 6 :(得分:1)

ConcurrentModificationException的javadoc包含答案:

  

请注意,此异常并不总是表示某个对象已被不同的线程同时修改。如果单个线程发出违反对象合同的一系列方法调用,则该对象可能会抛出此异常。例如,如果线程在使用失败快速迭代器迭代集合时直接修改集合,则迭代器将抛出此异常。

解决问题的方法是不这样做。

即,(正如其他人所说)如果需要同时进行迭代和修改,请使用迭代器提供的方法,而不是直接修改集合。