Re: Yet another ConcurrentModificationException question
Heiner K?cker wrote:
Eric Sosman schrieb
Heiner K?cker wrote:
Andy Chambers schrieb
Apologies for asking about this FAQ. I have looked up the relevant
java tutorial but I just want to check my understanding with the
following example.
Iterator oIterator = m_oCollection.iterator();
while( oIterator.hasNext()) {
Element oElement = (Element)oIterator.next();
String sOIDValue =
oElement.getAttribute(oElement.getOIDKey());
if( sOIDValue != null && sOIDValue.equals(sElementOID) ) {
// We have a match
return oElement;
}
}
If I know that neither getAttribute() or getOIDKey() can alter the
"structure" of m_oCollection, is it true to say that a
ConcurrentModificationException thrown from within the body of the
while loop above, *must* have been caused by another thread altering
the structure of m_oCollection?
So to prevent this from happening, I can make m_oCollection a
synchronized Vector (currently it is just a normal vector), and put
this while loop inside a synchronized block.
Use a for loop , no iterator.
If you mean
for (Object obj : m_oCollection) {
Element oElement = (Element)obj;
}
... there *is* an Iterator, hidden by the syntax but present anyhow.
I dont mean the for each loop.
Use the for loop:
for ( int i = 0; i < vector.size() ; i++ )
{
final Element oElement;
/**
* synchronized block for check
* vector size and get element in
* one atomar operation
*/
synchronized( vector )
{
if ( i < vector.size() )
{
oElement = (Element)vector.get( i );
> [...]
Thanks for the clarification. I wouldn't recommend this
pattern, though, because other threads can still interfere
and there'll be no ConcurrentModificationException to alert
you to the interference.
Here's the kind of scenario I'm thinking of: Suppose the
Vector holds "Alice", "Betty", "Carol", in that order. Now
consider two threads, T1 running the code above and T2 making
modifications to the Vector:
T1: i = 0, synchronize, i<3 -> true, desynchronize
T1: synchronize, i<3 -> true, get "Alice", desynchronize
T2: synchronize, delete "Alice" and slide the
remainder leftward, desynchronize
T1: i = 1, synchronize, i<2 -> true, desynchronize
T1: synchronize, i<2 ->true, get "Carol", desynchronize
T1: i = 2, synchronize, i<2 -> false, desynchronize,
loop exits
Observe that T1 has completely missed "Betty", even though
"Betty" was in the Vector the whole time and is in fact
still there.
A related problem arises if T2 inserts "Adelaide" at the
start of the Vector after T1 has processed that position: T1
would process "Alice" twice. (With enough insertions and
unlucky timing, T1 could process "Alice" N times.)
ConcurrentModificationException is not the end of the world,
but a red flag that warns you of a race condition in your code,
something that needs to be fixed. Suppressing the exception
means the code won't suddenly die, but that doesn't mean it's
living well ...
--
Eric Sosman
esosman@ieee-dot-org.invalid