我使用了同步列表,但仍然遇到了ConcurrentModificationException异常。

15

我在多线程环境下使用 Vector 而不是 ArrayList 来创建一个线程安全的列表。但当我尝试在迭代中添加项目到 Vector 时,我一直收到 ConcurrentModificationException 异常。为什么会发生这种情况,如何避免?


2
并发不等于并行。即使是单线程,也可能会出现ConcurrentModificationException异常。 - John Vint
3个回答

9

在迭代Vector时不能修改它。将要添加的项目存储在单独的Vector中,在循环结束时将它们移动到Vector中,或者在原始Vector的副本上进行循环。

添加: 要在Java中获取Vector周围的互斥锁,请在两个函数中执行此操作:

synchronized (list) {
  // modifying list
}

并且:

synchronized (list) {
  // iterating over list
}

当然,我假设列表的名称为list

4
注:即使在单线程程序中也适用。 - svckr
你的意思是它在单线程程序中成立吗? - Shelef
1
您不能在迭代列表时修改它,即使在单线程程序中也是如此。修改底层列表会使迭代器失效。 - fredrik
将要添加的项目存储在单独的向量中,并在循环完成时将它们移动到向量中,或者循环遍历原始向量的副本。或者使用标准JDK中已经存在的类来完成这个任务:CopyOnWriteArrayList。 - assylias
1
@assylias那不是那个类的作用。它会复制列表并丢弃旧列表。我的建议是等到迭代器完成后再添加新项。 - fredrik
显示剩余6条评论

2

如果您想在迭代过程中添加项目,您需要使用ListIterator。使用Vector并不能绕过这个规则(显然),所以我建议使用ArrayList代替。


如果涉及到多个线程,我认为在迭代时使用ListIterator添加元素是不安全的。 - assylias
1
@assylias,我误解了问题,我只是在处理“ConcurrentModificationException”。 - mre

2
如果您需要同时迭代和并发添加到列表中,应该使用一个并发列表,例如 CopyOnWriteArrayList。请注意,如果您向列表中写入大量内容,则效率可能不高。
否则,如果您使用 Vector 或 synchronizedList,请在迭代时持有列表的锁定。这将防止异常,但也会阻止并发操作...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接