[concurrency-interest] Thread-safety of hasMoreElements() of Vector

Mike Duigou mike.duigou at oracle.com
Tue Jul 24 14:14:21 EDT 2012


On Jul 24 2012, at 08:19 , Praveen Kumar Jha wrote:
>> 
> 
>> 
>> If the backing vector is changing on some other thread then Enumeration is
>> not a suitable API.  (This is probably the logic applied by the implementer
>> who decided not to bother sync'ing hasMoreElements.)
> 
> 
> But if that is the case then why is 'Vector.this' synchronized in
> nextElement() method?

To avoid accidentally generating a ArrayIndexOutOfBoundsException if the Vector shrinks or (just as bad) returning an element from the array that is not part of the Vector.

> As I understand, the behavior of both hasMoreElements() and
> nextElement() should be on the same lines as far as use of Enumeration
> in multithreaded case is concerned.

They could be but since the possibility of modification between hasMoreElements and nextElement exists making hasMoreElements synchronized on the vector wouldn't really solve anything. For true safety you would have to synchronize on the Vector outside of calls to hasMoreElements/nextElement. ie.

Vector vector;
Enumeration enumer = vector.elements();
synchronized(enumer) {
   while(enumer.hasMoreElements()) {
     Object object = enumer.nextElement();
     System.out.println(object);
   }
}

Without the surrounding synchronized it is possible that this snippet will.
- print all of the elements. (Yay!)
- print something odd (duplicate elements, miss elements, etc.) based upon concurrent modification
- fail with a NoSuchElementException if final element is concurrently removed after hasMoreElements() but before nextElement()

> And, I am considering the case
> when a thread is reading Vector using Enumeration while other thread
> is mutating it.

Probably a bad idea. Concurrent use of Vector should probably be limited to either non-structural modifications. ie. changes which don't change the size of the collection or very well ordered changes such as using Vector as a LIFO or FIFO (and there are better choices for this). If you are using Vector as a FIFO then perhaps just use removeElementAt(int index). Assuming only one thread is removing elements you aren't going to run into problems with atomicity in this usage.

Mike


More information about the Concurrency-interest mailing list