ConcurrentModificationException over list

时间:2011-06-07 18:46:54

标签: java concurrency

我正在尝试迭代一个对象列表。我收到ConcurrentModificationException错误。但是我没有更改/删除对象。 game.getRooms()方法也是同步的。我做错了什么?

Iterator<Room> it = game.getRooms().iterator();
     while (it.hasNext()) {
        Room room = it.next();
        synchronized (room) { 
           Image tile;
           if (room.getTile() == Tiles.WALL) {
              tile = TileGraphics.wall;
           } else if (room.getTile() == Tiles.EXIT) {
              tile = TileGraphics.exit;
           } else {
              tile = TileGraphics.floor;
           }
           tile.setAlpha(room.getLight());
           tile.draw(room.getX() * tile.getWidth(), room.getY() * tile.getHeight());
        }
     }

堆栈跟踪:

  

java.util.ConcurrentModificationException       at java.util.AbstractList $ Itr.checkForComodification(Unknown Source)       at java.util.AbstractList $ Itr.next(Unknown Source)       at game.screens.GameScreen.render(GameScreen.java:62)       at org.newdawn.slick.state.StateBasedGame.render(StateBasedGame.java:199)       在org.newdawn.slick.GameContainer.updateAndRender(GameContainer.java:681)       在org.newdawn.slick.AppGameContainer.gameLoop(AppGameContainer.java:408)       在org.newdawn.slick.AppGameContainer.start(AppGameContainer.java:318)       在game.Main.main(Main.java:23)   Tue Jun 07 22:05:03 EEST 2011 ERROR:Game.render()失败 - 检查游戏代码。   org.newdawn.slick.SlickException:Game.render()失败 - 检查游戏代码。       在org.newdawn.slick.GameContainer.updateAndRender(GameContainer.java:684)       在org.newdawn.slick.AppGameContainer.gameLoop(AppGameContainer.java:408)       在org.newdawn.slick.AppGameContainer.start(AppGameContainer.java:318)       在game.Main.main(Main.java:23)

第62行是Room room = it.next();

4 个答案:

答案 0 :(得分:4)

当然,代码会在另一个线程中的其他位置修改该列表。因此,一个选项是创建列表的副本并迭代它(使用foreach):

List<Room> copy = new ArrayList<Room>(game.getRooms());
for (Room room : copy) {..}

答案 1 :(得分:3)

如果在多线程应用程序中使用此列表,则任何线程都可以 访问列表并使用迭代器修改/迭代支持列表。

您的列表是否使用同步包装器创建? (例如,Collections.synchronizedList(new ArrayList())。

同步列表的声明是不够的,也不仅仅是同步方法调用。迭代列表的每个位置都需要一个同步块,与列表同步。

阅读http://download.oracle.com/javase/6/docs/api/java/util/Collections.html#synchronizedList(java.util.List

答案 2 :(得分:0)

getRooms同步这一事实根本不会影响代码。它只会影响对getRooms()的调用。

最好的方法是尝试同步(游戏){game.getRooms(); .. iterate}

甚至同步(game.getRooms()){... iterate}

答案 3 :(得分:0)

Slick管理逻辑,渲染等所有线程,所以它可能是Slick中的另一个线程正在做 - 可能在逻辑线程中的某个地方(即游戏的'update()方法中的东西)。 / p>

如果您未对上述代码进行任何修改,为什么要同步?您是否在没有同步的情况下尝试过它以确定它是否有效?

鉴于Slick应该为你处理渲染和逻辑线程/循环,我认为你可能会有更好的运气,如果你放松了一点,让Slick做的事情。可能是你根本不需要在这里进行同步。