Java 中的同步线程
我有两个线程修改同一个对象,比如说 MyObject,因此已经同步了该对象。但在其中一个线程中,另一个对象被修改,这样做时必须调用 MyObject。
即
public void run(){
synchronized(MyObject){
...
anotherObject.modify();//<----calls MyObject
...
}
}
这导致了 ConcurrentModificationExceptions。我不知道如何解决这个问题。如果我不同步,当两个线程都尝试调用 MyObject 时,我会收到异常。我该如何解决这个问题?
更新:该代码适用于 Android 设备。我之前没有提到它,因为这里没有 Android 特定对象在起作用。 LogCat 输出不是很有帮助
02-03 02:47:43.660:错误/AndroidRuntime(5258):未捕获的处理程序:线程主线程由于未捕获的异常而退出 02-03 02:47:43.670:错误/AndroidRuntime(5258):java.util.ConcurrentModificationException 02-03 02:47:43.670:错误/AndroidRuntime(5258):在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)//<---在此方法中 Gamestate 的集合通过迭代 02-03 02:47:43.670: 错误/AndroidRuntime(5258): 在 com.jjg.myapp.gameunit.update(GameUnit.java:416)
我试图同步的对象本质上是一个名为 gs 的 GameState。它包含各种 ArrayList、数组和其他对象。 gs 不是静态的。
上面出现问题的方法是:
for(GameUnit gu : this.getBase().getGameState().getAllUnits()){//<---this is the problem line.
//do some stuff...
}
getAllUnits 返回 GameUnits 的 ArrayList (包括调用该方法的 GameUnit - 我不需要迭代器,因为没有删除或创建对象)。
I have two threads modifying the same object, lets say MyObject, and so have synchronized the object. But in one of the threads another object is modified and in so doing has to call MyObject.
I.e.
public void run(){
synchronized(MyObject){
...
anotherObject.modify();//<----calls MyObject
...
}
}
This is causing ConcurrentModificationExceptions. I don't know how to solve this. If I don't synchronize, I get exceptions as both threads try to call MyObject. How can I fix this?
UPDATE: The code is for the Android device. I didn't mention it before, because there are no Android specific objects in play here.
The LogCat output isn't very helpful
02-03 02:47:43.660: ERROR/AndroidRuntime(5258): Uncaught handler: thread main exiting due to uncaught exception
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)//<---in this method Gamestate's collections are iterated through
02-03 02:47:43.670: ERROR/AndroidRuntime(5258): at com.jjg.myapp.gameunit.update(GameUnit.java:416)
The Object that I was trying to synch is essentially a GameState called gs. It houses an assortment of ArrayLists, arrays and other objects. gs is not static.
The method above where the problem occurs is:
for(GameUnit gu : this.getBase().getGameState().getAllUnits()){//<---this is the problem line.
//do some stuff...
}
getAllUnits returns an ArrayList of GameUnits (including the GameUnit calling the method - I don't need an iterator as no objects are deleted or created).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您确实在问同样的问题:集合上的线程安全迭代。
最简单的解决方案是在迭代列表之前复制列表:
或者,您可以在集合本身上进行同步(请注意,要使此功能正常工作,您还必须在修改“所有单位”列表的任何位置进行同步):
You're really asking the same question as this: Thread-safe iteration over a collection.
The simplest solution is to copy the list before iterating through it:
Alternatively you can synchronize on the collection itself (note that for this to work, you also have to synchronize wherever you're modifying the "all units" list):
如果在使用迭代器时修改集合,则通常会引发 ConcurrentModificationException。 ——所以我的你被名字误导了,只是搜索了错误的问题。
A
ConcurrentModificationException
is often thrown if an collection is modified while using an iterator on it. -- So my you are mislead by the name and just search for the wrong problem.不,你不需要。只有 1 个线程正在修改
MyObject
,另一个线程被阻止。由于锁是租用的,因此拥有锁的线程将再次运行。
正如评论所述,您发布的代码并未显示您为获得该异常而实际执行的操作。
MyObject
是Collection
吗?您是否同时在其他地方修改此集合,即没有适当的同步?或者也许迭代?
在这种情况下,你会得到你所说的异常
No you don't.Only 1 thread is modifying
MyObject
the other is blocked.The thread that has the lock will go again since the lock is rentrant.
As comments stated the code you post is not showing what you actually do to get that exception.
Is
MyObject
aCollection
? Are you modifying this collection elsewhere concurrently i.e. without proper synchronization?Or perhaps iterating?
In this case you would get the exception you say
你不能这样做,这是循环逻辑。
您要么必须完全摆脱线程并确定明确的评估顺序,要么以其他方式共享数据。
一种可能的策略是将调用“anotherObject.modify”放入单独的可运行线程中,如下所示:
You cannot do this, it is circular logic.
You either have to get rid of the threads altogether and determine an explicit order of evaluation or share data in some other way.
One possible strategy is to put the call "anotherObject.modify" into a separate runnable thread like this: