문제

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