[java] Java Synchronized list

I have a pre-populated array list. And I have multiple threads which will remove elements from the array list. Each thread calls the remove method below and removes one item from the list. Does the following code give me consistent behavior ?

ArrayList<String> list = Collections.synchronizedList(new ArrayList<String>());

void remove(String item)
{
     do something; (doesn't work on the list)
     list.remove(item);
}

Thanks!

This question is related to java multithreading

The answer is


Yes, it will work fine as you have synchronized the list . I would suggest you to use CopyOnWriteArrayList.

CopyOnWriteArrayList<String> cpList=new CopyOnWriteArrayList<String>(new ArrayList<String>());

    void remove(String item)
    {
         do something; (doesn't work on the list)
                 cpList..remove(item);
    }

synchronized(list) {
    for (Object o : list) {}
}

From Collections#synchronizedList(List) javadoc

Returns a synchronized (thread-safe) list backed by the specified list. In order to guarantee serial access, it is critical that all access to the backing list is accomplished through the returned list ... It is imperative that the user manually synchronize on the returned list when iterating over it. Failure to follow this advice may result in non-deterministic behavior.


You can have 2 diffent problems with lists :
1) If you do a modification within an iteration even though in a mono thread environment, you will have ConcurrentModificationException like in this following example :

List<String> list = new ArrayList<String>();
for (int i=0;i<5;i++)
   list.add("Hello "+i);

for(String msg:list)
   list.remove(msg);

So, to avoid this problem, you can do :

for(int i=list.size()-1;i>=0;i--)
   list.remove(i);

2)The second problem could be multi threading environment. As mentioned above, you can use synchronized(list) to avoid exceptions.


That should be fine as long as you don't require the "remove" method to be atomic.

In other words, if the "do something" checks that the item appears more than once in the list for example, it is possible that the result of that check will be wrong by the time you reach the next line.

Also, make sure you synchronize on the list when iterating:

synchronized(list) {
    for (Object o : list) {}
}

As mentioned by Peter Lawrey, CopyOnWriteArrayList can make your life easier and can provide better performance in a highly concurrent environment.


It will give consistent behavior for add/remove operations. But while iterating you have to explicitly synchronized. Refer this link