0

I am reading Brian Goetz's Java Concurrency in Practice. I am on page 83 and 84 where he discusses ConcurrentModificationException. Specifically, he is describing how ConcurrentModificationException can occur if there is an active iterator iterating through a collection and another iterator is called on the collection.

He presents this code:

public class HiddenIterator{

    @GuardedBy("this")
    private final Set<Integer> set = new HashSet<Integer>();

    public synchronized void add(Integer i){ set.add(i); }
    public synchronized void remove(Integer i){ set.remove(i); }

    public void addTenThings(){
        Random r = new Random();
        for(int i = 0; i < 10; i++)
            add(r.nextInt());
        System.out.println("DEBUG: added ten elements to set " + set)
    }
}

He notes that the string concatenation in the println statement is really an iterator. What I want to know is how the fail-fast behavior here works, since the iterator here does not modify the collection. It only reads the collection without touching the collection's state. Why should this throw a ConcurrentModificationException when there is another iterator operating on the collection? It clearly contradicts the name of the exception, which indicates a concurrent modification.

Clearly, the choice to throw ConcurrentModificationException even on read is bound up in the implementation details of Iterator. Why was this implementation chosen? And if anyone can sketch out the details of this implementation that causes ConcurrentModificationException to be thrown even on read, that would be wonderful.

Allen Han
  • 1,163
  • 7
  • 16
  • I am not convinced that the @GuardedBy really works here, since the usage in the string concatenation doesn't acquire `this`. – Andy Turner Aug 10 '19 at 19:00
  • A `ConcurrentModificationException` is not related to multi-threading or synchronized or unsynchronized collections. It is about iterating over a collection and also modifying the collection through other means than that iterator (and that can happen on the same thread or on a different thread). See the duplicate for how the iterator does that. – Mark Rotteveel Aug 10 '19 at 19:04

1 Answers1

0

What I want to know is how the fail-fast behavior here works, since the iterator here does not modify the collection.

During the iteration the set could be modified by someone calling add or remove because addTenThings is not synchronized. In this case the iteration can throw a ConcurrentModificationException. Remember that all reads and writes have to be guarded by the same lock.

Stefan Feuerhahn
  • 1,564
  • 1
  • 14
  • 22