Why is there a ConcurrentModificationException even when list is synchronized?

snaggs picture snaggs · Aug 4, 2014 · Viewed 8.7k times · Source

I have Android multi-threading application.

There is some probability that two or more triggers might run the same part of code.

I have a list of objects.

I made it to be synchronized by Collections.synchronizedList

private List<WmGroupItemSample> mGroupItemSampleList;

mGroupItemSampleList = new ArrayList<WmGroupItemSample>();
mGroupItemSampleList = Collections.synchronizedList(mGroupItemSampleList);

However sometimes I get Exception on line:

Collections.sort(mGroupItemSampleList, new GroupItemSampleComparator());

java.util.ConcurrentModificationException
       at java.util.AbstractList$SimpleListIterator.next(AbstractList.java:62)
       at java.util.Collections.sort(Collections.java:1895)
  • Is this flow legal?
  • do I need create the copy and run sort on copy?
  • why Collections.synchronizedList doesn't prevent this Exception?

[EDIT]

GroupItemSampleComparator

public class GroupItemSampleComparator implements java.util.Comparator<WmGroupItemSample> {

    public GroupItemSampleComparator() {
        super();        
    }

    public int compare(WmGroupItemSample s1, WmGroupItemSample s2) {
       return ( (s2.getStartDate() - s1.getStartDate()) > 0 ) ? (-1) : (1);
    }
}

Thanks,

Answer

Bohemian picture Bohemian · Aug 4, 2014

The basic problem is that a synchronized list is not synchronized in a useful way.

The problem is that while its methods are synchronized, actions like moving elements that should be atomic are not, because the separate calls needed for the move are not synchronized together. It means other threads can get in between individual method calls. Thus synchronized collections are largely deprecated now.

Despite this flaw, if you have another thread add an element while your thread is sorting, you'll get this exception because sort iterates and changing the list during iteration causes the exception.

Fortunately, the JDK has new Collection classes that have industrial strength (and useful) synchronization, courtesy of the java.util.concurrent package.

Replace your list with a CopyOnWriteArrayList, don't "synchronize" it and you'll be good to go.