How to Resolve ConcurrentModificationException

The ConcurrentModificationException comes under RuntimeException, and may be thrown by the methods that have detected concurrent modification of an object when such modification is not allowed. When a thread is iterating over a Collection, generally it is not allowed for another thread to modify a Collection. The ConcurrentModificationException can arise in single threaded as well as in multi-threaded environment.

To understand the ConcurrentModificationException consider the following scenario:-

TestCase 1:-

import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;

public class TestCase1 {
 
    public static void main(String args[]){
        List<String> list = new ArrayList<String>();
         
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("e");
         
        Iterator<String> it = list.iterator();
        
        while(it.hasNext()){
            String value = it.next();
            System.out.println("List Value:"+value);
            if(value.equals("b")) 
              list.remove(value);
        }
    }
}

Output:-

value is :a
value is :b
Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
	at java.util.ArrayList$Itr.next(Unknown Source)
	at TestCase1.main(TestCase1.java:17)

The exception is thrown by main method because we are changing the arraylist structure by removing the value from it. Now question arises how Iterator checks that structure of list is modified or not? The answer is that ArrayList extends the AbstractList class in which an int variable modCount is defined who provides the number of times the list has been structurally modified.

How to avoid ConcurrentModificationException:-

In a single threaded environment, use iterator’s remove method to remove the object from collection object

Test Case 2:-

import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;

public class TestCase2 {
 
    public static void main(String args[]){
        List list = new ArrayList();
         
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("e");
         
        System.out.println("size before modification :"+list.size());
        Iterator it = list.iterator();
        
        while(it.hasNext()){
            String value = it.next();
            if(value.equals("b")) 
              it.remove();
        }
        System.out.println("size after modification :"+list.size());
    }
}

Output:-

size before modification :5
size after modification :4

In a multi threaded environment we can avoid the ConcurrentModificationException by implementing the following techniques:-

Synchronization:-In a multi threaded environment if you want that at a time only one thread can access or modify the same object then you can lock the object by putting it in a synchronized block. However this approach may reduce the performance of application and hence not recommended.

Synchronized Collection:-if we are using the jdk1.4 or lower version then we can use Synchronized Collection Methods of Collection class like Collections.synchronizedCollection(Collection c), Collections.synchronizedList(List list), Collections.synchronizedSet(Set s) , Collections.synchronizedMap(Map<K,V> m) etc, or if we are using jdk1.5 or above then we can use ConcurrentHashMap that allows concurrent modification of the Map from several threads without the need to block them and CopyOnWriteArrayList in which all mutative operations are implemented by making a fresh copy of the underlying array.

Test Case 3:-

import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
 
public class TestCase3 {
 
    public static void main(String[] args) {
 
        List list = new CopyOnWriteArrayList();
         
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("e");
         
        System.out.println("size before modification :"+list.size());

        Iterator it = list.iterator();
        
        while(it.hasNext()){
            String value = it.next();
            if(value.equals("b")){
            	list.remove("d");
            	list.add("f");
            	list.add("g");
            }
        }
        System.out.println("size after modification :"+list.size());
    }        
}

Output:-

size before modification :5
size after modification :6

So using the concurrent Collection classes or Synchronized Collection Method we can avoid the ConcurrentModificationException in the multi-threaded environment. Use Synchronized Collection Methods if you need to ensure data consistency and each thread needs to have an up-to-date view of the map. Use concurrent Collection classes if performance is critical, and each thread only inserts data, with reads happening less frequently.

Leave a Comment