質問

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.

役に立ちましたか?

解決

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?

他のヒント

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.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top