views:

703

answers:

1
 public synchronized X getAnotherX(){ 
  if(iterator.hasNext()){
   X b = iterator.next();
   String name = b.getInputFileName();
  ...
   return b;
  }
  else{return null;}
 }

despite the synchronized statement in the declaration header, i still get a ConcurrentModificationException Exception at the line where i use iterator.next(); whats wrong here ?

+1  A: 

ConcurrentModificationException usually has nothing to do with multiple threads. Most of the time it occurs because you are modifying the collection over which it is iterating within the body of the iteration loop. For example, this will cause it:

Iterator iterator = collection.iterator();
while (iterator.hasNext()) {
    Item item = (Item) iterator.next();
    if (item.satisfiesCondition()) {
       collection.remove(item);
    }
}

In this case you must use the iterator.remove() method instead. This occurs equally if you are adding to the collection, in which case there is no general solution. However, the subclass ListIterator can be used if dealing with a list and this has an add() method.

Ramon
i don't get it, i simply want a String which is (in this case in object called "b") .but well i tried to use iterator.remove(); but that didn't helped. same exception coming.
dayscott
It would be helpful if you posted your entire code for the method
Ramon
no problem: public synchronized Block getAnotherBlock(){ Block b = null; if(iterator.hasNext()){ b = iterator.next(); iterator.remove(); } String name = b.getInputFileName(); Integer []arr = blocksPerFileLeft.get(name); arr[1] += 1; blocksPerFileLeft.put(b.getInputFileName(), arr); currBlockPos++; //incr global var return b;
dayscott
Why not make the Iterator a local variable?
Ramon
i need it to be a object variable because the method getAnotherBlock() wants be called from different threads, so it can't be a local variable of the method. behind the iterator there is actually a linked list, so i could try to make the iterator local, like you proposed and call the remove() statement everytime, hmm - but i still don't get why my posted code doesn't work : /(how to mark code in a commment around here by the way, when i say " add comment there is no bar where i can highlight code snippets : / )
dayscott
Ok I see that in your case it actually is a threads issue so probably more complicated. Yeah then my feeling is the Iterator should definitely be a local variable, since they represent the current position in the list it is highly unusual to keep them outside the scope of a method.
Ramon
"since they represent the current position in the list it is highly unusual to keep them outside the scope of a method" but what do you do if you want to represent the current position in a list within a living object, not just a single method, than you have to put the iterator as a local variable of the object, don't you ? so what do you exactly mean when you say "it is highly unusul" ? how is this kind of problem solved then "in reality" ? ( i am not a very experienced programmer, so i hope you don't mind if i ask )
dayscott
Ok, thats fine but in this case *any* modification to the list after you have taken out the iterator (i.e. called the `iterator()` method) will result in `ConcurrentModificationException` even if every access to the collection is synchronized. You cannot interleave calls to iterator methods with mutations to the collection. To see the reason for this, think about how the iterator is implemented and what you expect to happen if someone inserts or removes elements before or after the iterator's current position.
Ramon