我已经坚持了一段时间了,所以非常感谢任何帮助。
我有以下代码部分:
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)
答案 0 :(得分:2)
如果没有看到代码的其余部分,则可以通过以下方式声明ballList
:
private final List<Ball> ballList = Collections.synchronizedList(...);
synchronizedList
的所有操作都会尝试在每个方法之前自行同步,只要您保持当前的synchronized(ballList)
,就可以使迭代完全安全。
答案 1 :(得分:1)
在我们可以看到的代码中,ballList
实际上没有被修改,并且使用多个线程读取是安全的。其他一些代码可能会修改ballList
(上面的@pst指出它可能是updatePosition
)。
run
和paintComponent
方法看起来不需要同步,因为它们不在外部共享状态(因为您正在同步ballList
的相关部分代码)。
编辑:
根据您的修改,processCollisions
看起来ballsLocal
仅在ballsLocal
上为一个短块进行同步,而不是在synchronized (ballsLocal) {
initialSize = ballsLocal.size();
}
未实际修改的时候
processCollisions
虽然this
已同步,但隐式同步synchronized
。如果您的方法仅使用this
关键字而未指定要同步的内容在不同的类中,则正在同步的{{1}}是不同的。如果你需要在不同的类之间进行同步,那么ball类应该处理同步,或者你需要一个共享的锁。
答案 2 :(得分:0)
在processCollisions()
中,您要将对象添加到同步块之外的列表中。请注意,只有一条行似乎是同步的,即获得大小的行,但稍后(接近结尾)您要添加到列表中。在循环完成之前,您不需要关闭同步块。