Thursday, November 02, 2006

Using Collections.synchronizedList

Till yesterday i was thinking that if i use a Collections.synchronizedList () and use that returned list , i need not synchronize that list. But after running my app i found that i was getting the ConcurrentModificationException which encouraged me to look at the java api ocs and then i found out that my conception was entirely wrong as can be seen from the exceprt below



It is imperative that the user manually synchronize on the returned list when iterating over it:
List list = Collections.synchronizedList(new ArrayList());
...
synchronized(list) {
Iterator i = list.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
Failure to follow this advice may result in non-deterministic behavior.

Seeing the above docs i was confused as to what is the usage of the synchronizedList??
If we are anyways synchronizing it externally then we can as well use the normal list and
synchronize it rather than using the synchronized list.I stilll have to find out the reason for this
can anyone put some light on me regarding this?

4 Comments:

At 4:09 AM , Blogger Parag said...

The SynchronizedList synchronizes all access methods to the list by providing a synchronized wrapper on top of the list. You must however always use the wrapper (SynchronizedList) to access the list elements.
The Iterator is not synchronized, because the moment anything changes in the list we get a ConcurrentModificationException. This means that simply synchronizing individual access methods (next, remove) will not be useful, because if the list is modified externally the Iterator becomes useless.
When using an Iterator, we actually have to synchronize the entire block that iterates over the list.
The correct usage when using Lists in multiple threads, is to get a SynchronizedList and use it everywhere. In the code that uses an Iterator over that List you have to be sure that you synchronize the block on the synchronizedList object.

 
At 5:24 AM , Blogger Milan Mehta said...

Still agree with BM's point, that the synchronization wrapper is useless, if we ultimately need to synchronize explicitly.

Ideally, the synchronization wrapper's iterator() method should implicitly synchronize over the underlying object.

Would really be interested in finding out why Sun chose not to provide this.

 
At 5:36 AM , Blogger Milan Mehta said...

Here's what I found on the subject in the Sun Java Tutorials

The relevant paragraph to answer the question is -
"In the face of concurrent access, it is imperative that the user manually synchronize on the returned collection when iterating over it. The reason is that iteration is accomplished via multiple calls into the collection, which must be composed into a single atomic operation."

Normally, you want to iterate over each element of a collection AND do one or more operations on the element. The retrieval of the element as well as the operation(s) need to be done in one atomic action, and all changes to the underlying collection need to be prevented until the relevant operation(s) are complete.

To allow this control, it makes sense to require the user to explicitly manage the synchronization. If not, you would land up extracting the element, and before you completed the operation on the element, some other thread might land up deleting the element itself.

 
At 12:18 PM , Blogger RaghuK said...

many thanks folks for discussing this moot point. I will
rephrase some thoughts already discussed.

Bottomline all threads implicitly or explicitly must synchronize
on the synchronizedList object or else the 'List object' they are
dealing with will not be be consistent.

It is obvious why all threads must use the synchronizedobject for
regular operations structural modification add, remove operations.
But an operation such as iteration depends on the underlying structure
and any changes structure can cause adverse effects on the iteration
process itself. hence the structure needs to be protected from being
altered by other threads. This protection can be achieved only if the
iterating thread and the other (structure altering) threads synchronize
on the 'same' object. Hence the iterating thread has to explicitly
synchronize on 'SynchronizedList'.

 

Post a Comment

Subscribe to Post Comments [Atom]

<< Home