2

In HashSet.java in JDK 1.6, there are some comments about the fail-fast property of HashSet's iterator.

The iterators returned by this class's iterator method are fail-fast: if the set is modified at any time after the iterator is created, in any way except through the iterator's own remove method, the Iterator throws a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

I can understand the above paragraph because It's pretty simple and clear, but I cannot understand the following paragraph. I may understand it if I have some simple examples showing that a fail-fast iterator can even fail.

Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.

ig0774
  • 39,669
  • 3
  • 55
  • 57
Heejin
  • 4,463
  • 3
  • 26
  • 30
  • 3
    It's basically saying, do not rely on Java to definitely let you know that you are abusing iterators. Simply put, you cannot modify a list while you are iterating through it. – thatidiotguy Aug 27 '12 at 16:07

2 Answers2

2

EDIT: Sorry I used a list, but it's the same idea. This is about iterator, not the Collection behind it.

EDIT2: Also this is far more likely to happen in a multi-threaded environment, where you have two threads, one reading, one writing. These are harder to see when you are coding. To fix those you need to implement Read/Write locks on the list to avoid this.

Here is a code example for the comment:

Iterator itr = myList.iterator();

while(itr.hasNext())
{
    Object o = itr.next();

    if(o meets some condition)
    { 
        //YOURE MODIFYING THE LIST
        myList.remove(o);
    }
}

What the specs is saying is that you cannot rely on code like this:

while(itr.hasNext())
{
     Object o = itr.next();

     try
     {
         if(o meets some condition)
            myList.remove(o);
     }
     catch(ConcurrentModificationException e)
     {
         //Whoops I abused my iterator. Do something else.
     }
}

Instead you should probably add things to a new list and then switch the myList reference to the one just created. Does that explain the situation?

thatidiotguy
  • 8,701
  • 13
  • 60
  • 105
2

The idea behind the second paragraph is to prevent you from writing code like this:

boolean ok = false;
do {
    try {
        doTheModification();
        ok = true;
    } catch {
        // Consurrent modification - retry
    }
} while (!ok);

While this is not a good code to start with, the comment states that this code is invalid (as opposed to, say, sub-optimal). They say that the exception may not follow at all, so the above loop may produce a failure silently.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 1
    This is a very succinct example of what you could code (naively and wrongly) if you had several threads working on the same list. Instead you want to use the Java languages read/write locks. Not rely on ConcurrentModificationException. – thatidiotguy Aug 27 '12 at 16:14