I’m trying to iterate through a loop on one thread, like so:
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();
}
However, I have another thread (the Swing event thread) which can add to this object. Hence, ConcurrentModificationException. I tried obtaining a lock by surrounding the code with synchronized (chain) { ... }, but I still get the errors.
As a bit of a Java synchronization newbie, I’m a little confused as to why. I would expect this to make the loop thread-safe, but evidently, it is not.
Interestingly, chain is an instance of a custom class, but it is only a thin wrapper around a LinkedList. The list itself is private, and there’s no way for an external class to retrive it directly (there are methods to explicitly add/remove objects), so I wouldn’t expect this to affect the outcome.
The meaning of
is
cto be unlockedccSo if you synchronize in your thread, then your thread will wait for
cto be unlocked and then dive in.Now, if you do not synchronize the code on the other thread that modifies
c, that code is going to just go ahead and modifycwithout waiting for a lock. Synchronizing a block in one thread does not make another thread wait for a lock. If the other thread has a line such asthat is not in a synchronized block, then it’s going to do the add no matter what. This is the cause of your exception. It is also the reason why you saw the exception even though you put the code in your thread in a synchronized block: your code was “playing by the rules” but the other thread couldn’t have cared less.
Be careful about synchronizing long-running code though. You are better off, as Stephen C says, to use a concurrent collection type.