Thread Safety issues with Vector and Hashtable.
Overview
Even though these classes are legacy replaces which were replaced in Java 1.2 (1998) they remain widely using. One misconception is that they are synchronized and there for thread safe.Is Iterator thread safe?
For many collections the Iterator is not thread safe. They fail fast by throwing a ConcurrentModiciationException. However throwing this exception is not guaranteed and the counter used to detect this situation is not volatile.Collection | Iterator behavior |
---|---|
ArrayList, LinkedList, TreeSet | Usually throws a ConcurrentModicationException |
CopyOnWriteArraySet, CopyOnWriteArrayList | Consistent for the state of the collection at a given point in time |
ArrayBlockingQueue, LinkedBlockingQueue | Weakly consistent, won't throw an error |
ArrayBlockingQueue, LinkedBlockingQueue | Also weakly consistent, won't throw an error, the Iterator is sorted |
PriorityQueue | Also weakly consistent, even though the collection is sorted , the Iterator is not sorted. |
Enumeration is thread safe?
Every method is synchronized so the collection should be thread safe, unfortunately Enumeration has to be used in two parts, hasMoreElements() and nextElement(), each method is thread safe, but another thread can make changes in between these two calls which can cause the Enumeration to fail.VectorThe line between hasMoreElements() and nextElement() show what another thread can randomly do. This causes the nextElement() to throw a NoSuchElementException.ints = new Vector (); ints.add(1); ints.add(2); Enumeration en = ints.elements(); int count = 0; while(en.hasMoreElements()) { OnThreadB: if(count++ == 1) ints.remove(0); System.out.println(en.nextElement()); }
How to make Enumeration thread safe?
You need to lock the collection for the life of the Enumeration, This can be used for Iterators as well (though for different reasons)Vectorints = new Vector (); ints.add(1); ints.add(2); synchronized (ints) { Enumeration en = ints.elements(); while(en.hasMoreElements()) { // another there cannot do some thing here. System.out.println(en.nextElement()); } }
Conclusion
Don't assume that making every method synchronized will make a collection thread safe, you also have to consider whether methods will be used in combination and whether one depends on another.Ideally you should make every method independent to avoid this issue.
Comments
Post a Comment