Java Synchronized list

Posted on

Java Synchronized listError is an illegal operation performed by the user which results in the abnormal working of the program. By now, you’ve probably seen a few errors, either when compiling or running your code like Java Synchronized list. It can be frustrating, but they can also give you a lot of information about exactly how you can fix the problems in your code about java and multithreading. In this post covers the types of errors you’ll see when programming in Java, and how to fix them. Don’t pay any attention to the number of errors. Just read the first error message and work on fixing that error.

Problem :

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!

Solution :

Yes, Just be careful if you are also iterating over the list, because in this case you will need to synchronize on it. From the Javadoc:

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());
}

Or, you can use CopyOnWriteArrayList which is slower for writes but doesn’t have this issue.

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.

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.

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

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) {}
}

Leave a Reply

Your email address will not be published. Required fields are marked *