Question regarding iteration over synchronized list

Advertisement
I've got an A-Life program I work on for fun. I thought I understood (sorta) synchronized collections, but this puzzles me. The method body is as follows:
* Create new animals from existing animals
* @return The cohort of newborn animals
public List<IAnimal> regenerate() {
List<IAnimal> children = new ArrayList<IAnimal>();
synchronized (animalList) {
Iterator<IAnimal> it = animalList.iterator();          // must be in synchro block according to JDK notes
     while (it.hasNext()) {
     IAnimal a = it.next();
     if (a.isPregnant() && ((GeneModel.getInstance().getTicks() % getEnvironment().getAnimal().getReproCycle()) == 0)) {
     IAnimal child = a.reproduce();
     children.add(child);                    // newborns
//     animalList.add(child);                    // the whole population //THROWS CME!
     animalList.addAll(children); // does not throw CME
return children;
Animal list is a synchronized list (backed by and ArrayList). Note that I've synchronized on the list, yet adding children individually throws a ConcurrentModificationException (I did overwrite the add() method on the backing list, but I wouldn't think that would be a problem; it might be in that it iterates over itself... but synchronizing that doesn't help, either).
Anyhow, doing an addAll outside of the synchronization block works fine (also works if I loop through the children and add them at this point).
Is it my override of the add() method? From what I can see, the synchronized wrapper just adds a mutex to each access method in the backing list. Here's the method override:
List<IAnimal> backingList =
new LinkedList<IAnimal>() {
* Checks that we're not putting one animal on top of another. If we are, we generate a new animal and
* try again.
* @param animal The animal to be added
* @return true
public boolean add(IAnimal animal) {
boolean added = false;
outer:
do {
// synchronized (this) {                // DIDN'T HELP
Iterator<IAnimal> iAnimals = iterator();
while (iAnimals.hasNext()) {
//FIXME: this algorithm assumes square animals
Point existingAnimalLocation = iAnimals.next().getLocation();
double distance = existingAnimalLocation.distance(animal.getLocation());
if (distance < animal.getSize().getWidth()) {
animal = new Animal();
continue outer;
//} //end unhelpful synchro block
super.add(animal);
added = true;
while (!added);
return added;
} // end method add
};
Advertisement

Replay

Your code is not formatted (use code tags for this) but it seems to me that you add elements to the list while you iterate over it, hence a ConcurrentModificationException is thrown. Use a ListIterator if you want to add to the list while iterating.