3

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

我有以下代码部分:

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)
4

3 回答 3

2

在没有看到其余代码的情况下,一种解决方法是声明ballList如下:

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

在每个方法之前尝试对自身进行同步的所有操作,synchronizedList只要您保持当前synchronized(ballList)的 s 就位,这将使您的迭代完全安全。

于 2012-07-24T02:58:08.107 回答
1

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

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

编辑:

根据您的编辑,看起来processCollisions只有ballsLocal一个短块同步,而ballsLocal不是实际上没有被修改的时间

synchronized (ballsLocal) {             
  initialSize = ballsLocal.size();
}

虽然processCollisions是同步的,但隐式同步于this. 如果您的方法只使用synchronized关键字而不指定要同步的内容在不同的类中,则this同步的对象是不同的。如果您需要像这样在不同的类之间进行同步,那么球类应该处理同步,或者您需要一个共享的锁。

于 2012-07-24T02:59:03.127 回答
0

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

于 2012-07-24T03:28:44.523 回答