在每个循环的同步中仍然会抛出ConcurrentModificationExceptions

Ale*_*ing 3 java concurrency synchronized

我试图在一个线程上迭代循环,如下所示:

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();
}
Run Code Online (Sandbox Code Playgroud)

但是,我有另一个线程(Swing事件线程)可以添加到此对象.因此,ConcurrentModificationException.我尝试通过包围代码来获取锁定synchronized (chain) { ... },但我仍然得到错误.

作为一个Java同步新手,我有点困惑为什么.我希望这可以使循环线程安全,但显然,它不是.

有趣的chain是,它是一个自定义类的实例,但它只是一个很薄的包装器LinkedList.列表本身是私有的,外部类没有办法直接检索它(有明确添加/删除对象的方法),所以我不希望这会影响结果.

Ray*_*oal 11

的含义

synchronized (c) {
    ... code that uses c ...
}
Run Code Online (Sandbox Code Playgroud)

  • 等待c解锁
  • c
  • 执行身体
  • 开锁 c

因此,如果您在线程中进行同步,那么您的线程将等待c解锁然后潜入.

现在,如果您同步修改的其他线程上的代码c,那么该代码将继续进行修改c而无需等待锁定.在一个线程中同步块不会使另一个线程等待锁定.如果另一个线程有一行如

c.add(someOtherTask)
Run Code Online (Sandbox Code Playgroud)

这不是在同步块中,无论如何都会添加.这是您的例外原因.这也是为什么你看到的例外,即使你把代码在你的线程在同步块的原因:你的代码是"遵守游戏规则",但其他线程不可能关心较少.

但要注意同步长时间运行的代码.正如Stephen C所说,你最好使用并发集合类型.