-
20-09-2019 - |
题
如果在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
方法。因此可以删除。
我同意别人的看法 Iterator
和 remove()
.
关于同步,我想补充说,同步旨在控制交互 在不同的线程之间.
对象具有多种方法是典型的,并且一种方法会称呼另一种方法。因此,语言设计师认为同一线程不会被同步封锁。
另外,考虑一下,它的线程被封锁了,等待着自己,你有一个宏伟的 饥饿 看法! ;-)
因此,这回答了您的一个问题:不可能通过同步代码来避免问题。
利用 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());
}
}
不隶属于 StackOverflow