如果在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());
}
有帮助吗?

解决方案

  • 如果您要从列表中删除项目,则可以通过调用 iterator.remove() 代替 list.remove(iterator.next())

  • 如果要添加一个项目 - 好吧,请创建迭代列表的副本,然后在此处添加

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

其他提示

能够 修改 Collection 如果您这样做的话,请迭代 Iterator 界面。您可以使用 Iterator.remove() 删除元素。

在迭代时,您无法修改它。同步在这里无济于事。

编辑:我忘记了迭代器确实有 remove 方法。因此可以删除。

我同意别人的看法 Iteratorremove().


关于同步,我想补充说,同步旨在控制交互 在不同的线程之间.

对象具有多种方法是典型的,并且一种方法会称呼另一种方法。因此,语言设计师认为同一线程不会被同步封锁。

另外,考虑一下,它的线程被封锁了,等待着自己,你有一个宏伟的 饥饿 看法! ;-)

因此,这回答了您的一个问题:不可能通过同步代码来避免问题。

利用 CopyOnWriteArrayList 而不是同步数组列表

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());
   }
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top