我有两个线程修改同一个对象,比方说MyObject,所以已经同步了对象。但是在其中一个线程中,另一个对象被修改,因此必须调用MyObject。
即
public void run(){
synchronized(MyObject){
...
anotherObject.modify();//<----calls MyObject
...
}
}
这导致ConcurrentModificationExceptions。我不知道如何解决这个问题。如果我不同步,我会得到异常,因为两个线程都试图调用MyObject。我该如何解决这个问题?
更新:该代码适用于Android设备。之前我没有提到它,因为这里没有Android特定的对象。 LogCat输出不是很有帮助
02-03 02:47:43.660:ERROR / AndroidRuntime(5258):未捕获的处理程序:由于未捕获的异常而导致主线程退出 02-03 02:47:43.670:ERROR / AndroidRuntime(5258):java.util.ConcurrentModificationException 02-03 02:47:43.670:ERROR / AndroidRuntime(5258):at java.util.AbstractList $ SimpleListIterator.next(AbstractList.java:64) 02-03 02:47:43.670:ERROR / AndroidRuntime(5258):at com.jjg.myapp.gameunit.findEnemy(MoveableUnit.java:656)//&lt; ---在此方法中,Gamestate的集合通过迭代完成 02-03 02:47:43.670:ERROR / AndroidRuntime(5258):at com.jjg.myapp.gameunit.update(GameUnit.java:416)
我试图同步的对象本质上是一个名为gs的GameState。它包含各种ArrayLists,数组和其他对象。 gs不是静态的。
出现问题的上述方法是:
for(GameUnit gu : this.getBase().getGameState().getAllUnits()){//<---this is the problem line.
//do some stuff...
}
getAllUnits返回GameUnits的ArrayList(包括调用方法的GameUnit - 我不需要迭代器,因为没有删除或创建对象)。
答案 0 :(得分:1)
如果在使用迭代器时修改了集合,则通常会抛出ConcurrentModificationException
。 - 所以我的名字会误导你,只是寻找错误的问题。
答案 1 :(得分:1)
你真的问这个问题:Thread-safe iteration over a collection。
最简单的解决方案是在迭代之前复制列表:
for(GameUnit gu : new ArrayList<GameUnit>(this.getBase().getGameState().getAllUnits()))
或者你可以在集合本身上进行同步(请注意,为了使其正常工作,你还需要在修改“所有单位”列表的任何地方进行同步):
ArrayList<GameUnit> units = this.getBase().getGameState().getAllUnits())
synchronized (units) {
...
}
答案 2 :(得分:0)
我有两个线程修改同一个对象,比方说MyObject,和 所以已同步对象。
不,你没有。只有1个线程正在修改MyObject
,另一个线程被阻止。
但是在其中一个线程中,另一个对象被修改并且这样做 必须调用MyObject。
由于锁是租用的,具有锁的线程将再次出现。
正如评论所述,您发布的代码并未显示您实际执行的操作以获取该异常。
MyObject
是Collection
吗?您是否同时在其他地方修改此集合,即没有适当的同步?
或者也许迭代?
在这种情况下,你会得到你说的例外
答案 3 :(得分:0)
你不能这样做,它是循环逻辑。
您必须完全摆脱线程并确定明确的评估顺序或以其他方式共享数据。
一种可能的策略是将调用“anotherObject.modify”放入一个单独的可运行线程中,如下所示:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
anotherObject.modify();
}
});