2

如果在 doSomething() 中修改了列表,此代码将引发并发修改异常。是否可以通过将代码包含在某个同步块中来避免它?

List l = Collections.synchronizedList(new ArrayList());

// normal iteration -- can throw ConcurrentModificationException
// may require external synchronization
for (Iterator i=list.iterator(); i.hasNext(); ) {
  doSomething(i.next());
}
4

6 回答 6

7
  • 如果您要从列表中删除一个项目,您可以通过调用iterator.remove()而不是list.remove(iterator.next())

  • 如果您要添加一个项目 - 好吧,创建迭代列表的副本并将其添加到那里

  • 如果上面的代码片段是同一方法的一部分,那么您不需要同步列表或同步块 - 没有其他线程可以访问本地列表。

于 2010-02-12T06:49:36.837 回答
3

如果您通过界面这样做,您可以修改一段Collection时间迭代它。Iterator您可以使用Iterator.remove()删除元素。

于 2010-02-12T06:49:59.550 回答
0

迭代时不能修改它。同步在这里无济于事。

编辑:我忘了迭代器确实有remove方法。所以可以去掉。

于 2010-02-12T06:47:28.410 回答
0

我同意其他人关于Iterator和的观点remove()


关于同步,我想补充一点,同步是为了控制不同线程之间的交互而设计的。

一个对象通常有几个同步的方法,并且一个会调用另一个。所以语言设计者决定同一个线程在同步时不会被他自己阻塞。

还有,想一想,它有一个线程在等待自己,你有一个壮丽的饥饿视角!;-)

所以这回答了你的一个问题:通过同步你的代码是不可能避免这个问题的。

于 2010-02-12T07:30:00.493 回答
0

使用CopyOnWriteArrayList而不是同步的数组列表

于 2010-02-12T07:45:26.810 回答
0
List l = Collections.synchronizedList(new ArrayList());

synchronized(l) { 
   // normal iteration -- can throw ConcurrentModificationException
   // may require external synchronization
   for (Iterator i=list.iterator(); i.hasNext(); ) {
      doSomething(i.next());
   }
}
于 2013-10-25T06:49:02.900 回答