Java-同步列表

时间:2012-07-24 02:49:37

标签: java arraylist synchronization

我已经坚持了一段时间了,所以非常感谢任何帮助。

我有以下代码部分:

BallThread.java
@Override
public synchronized void run() {
  while (numItersCompleted < maxNumIters) {
    completedThisIter = false;
synchronized (ballList) {
    for (Ball b : ballList) { // line 35
        b.updatePosition(ballPanel.getBounds(), ballList);
    }
}
 } // other stuff


Exception in thread "Thread-2" java.util.ConcurrentModificationException
at java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1091)
at java.util.ArrayList$SubList.listIterator(ArrayList.java:972)
at java.util.AbstractList.listIterator(AbstractList.java:300)
at java.util.ArrayList$SubList.iterator(ArrayList.java:968)
at Part2.BallThread.run(BallThread.java:35)

有时我会得到这个(BallPanel中的第36行)

java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:782)
at java.util.ArrayList$Itr.next(ArrayList.java:754)
at Part2.BallPanel.paintComponent(BallPanel.java:36)
at javax.swing.JComponent.paint(JComponent.java:1029)
at javax.swing.JComponent.paintToOffscreen(JComponent.java:5138)
at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:302)
at javax.swing.RepaintManager.paint(RepaintManager.java:1188)
at javax.swing.JComponent._paintImmediately(JComponent.java:5086)
at javax.swing.JComponent.paintImmediately(JComponent.java:4896)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:783)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:735)

3 个答案:

答案 0 :(得分:2)

如果没有看到代码的其余部分,则可以通过以下方式声明ballList

private final List<Ball> ballList = Collections.synchronizedList(...);

synchronizedList的所有操作都会尝试在每个方法之前自行同步,只要您保持当前的synchronized(ballList),就可以使迭代完全安全。

答案 1 :(得分:1)

在我们可以看到的代码中,ballList实际上没有被修改,并且使用多个线程读取是安全的。其他一些代码可能会修改ballList(上面的@pst指出它可能是updatePosition)。

runpaintComponent方法看起来不需要同步,因为它们不在外部共享状态(因为您正在同步ballList的相关部分代码)。

编辑:

根据您的修改,processCollisions看起来ballsLocal仅在ballsLocal上为一个短块进行同步,而不是在synchronized (ballsLocal) { initialSize = ballsLocal.size(); } 未实际修改的时候

processCollisions

虽然this已同步,但隐式同步synchronized。如果您的方法仅使用this关键字而未指定要同步的内容在不同的类中,则正在同步的{{1}}是不同的。如果你需要在不同的类之间进行同步,那么ball类应该处理同步,或者你需要一个共享的锁。

答案 2 :(得分:0)

processCollisions()中,您要将对象添加到同步块之外的列表中。请注意,只有一条行似乎是同步的,即获得大小的行,但稍后(接近结尾)您要添加到列表中。在循环完成之前,您不需要关闭同步块。