我正在尝试在一个线程上迭代一个循环,如下所示:
for (UnitTask task : chain) {
g.drawLine((int) task.getLocation().getX(), (int) task.getLocation().getY(), (int) currentPos.getX(), (int) currentPos.getY());
g.fillOval((int) task.getLocation().getX() - 2, (int) task.getLocation().getY() - 2, 5, 5);
currentPos = task.getLocation();
}
但是,我有另一个线程(Swing 事件线程)可以添加到这个对象。因此,ConcurrentModificationException
。我尝试通过用 synchronized (chain) { ... }
包围代码来获得锁,但我仍然遇到错误。
作为一个 Java 同步新手,我有点困惑为什么。我希望这会使循环线程安全,但显然不是。
有趣的是,chain
是自定义类的一个实例,但它只是 LinkedList
的薄包装。列表本身是私有(private)的,外部类无法直接检索它(有显式添加/删除对象的方法),所以我不认为这会影响结果。
最佳答案
意义
synchronized (c) {
... code that uses c ...
}
是
- 等待
c
解锁 - 锁定
c
- 执行正文
- 解锁
c
因此,如果您在您的线程中进行同步,那么您的线程将等待 c
解锁,然后潜入。
现在,如果您不同步修改c
的other 线程上的代码,该代码将继续执行并且修改 c
而不等待锁定。在一个线程中同步块(synchronized block)不会使另一个线程等待锁。如果另一个线程有这样一行
c.add(someOtherTask)
不在同步块(synchronized block)中,那么无论如何它都会执行添加。这是您异常(exception)的原因。这也是为什么即使将代码放在同步块(synchronized block)中的线程中也会看到异常的原因:您的代码是“按规则进行游戏”,但另一个线程根本不在乎。
但是要小心同步长时间运行的代码。正如 Stephen C 所说,您最好使用并发集合类型。
关于java - 在 for each 循环中同步仍然会抛出 ConcurrentModificationExceptions,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12444586/