Home » Java Basics » exceptions » java.util.concurrentmodificationexception – How to handle Concurrent Modification Exception

About Sotirios-Efstathios Maneas

Sotirios-Efstathios Maneas

Sotirios-Efstathios (Stathis) Maneas is a PhD student at the Department of Computer Science at the University of Toronto. His main interests include distributed systems, storage systems, file systems, and operating systems.

java.util.concurrentmodificationexception – How to handle Concurrent Modification Exception

The ConcurrentModificationException is a RuntimeException that may be thrown by methods that have detected concurrent modification of an object, when such modification is not permissible. An example of not permissible behavior is when a thread tries to modify the internal structure of a Collection, while another thread is iterating over it.

In general, the results of the iteration are undefined. Some iterators throw a ConcurrentModificationException when they detect such behavior. These iterators are called fail-fast iterators, as they stop the normal execution to report an error, rather that continuing in a non-deterministic way. Notice that this exception does not indicate that the object has been concurrently modified by a different thread. The exception is thrown even one thread is violating an object’s contract.

1. Error cases

In this section, we will describe and explain those cases that produce a ConcurrentModificationException.

Case 1: The Collection is internally modified, while a thread is iterating over it.

Example_v1.java:

import java.util.HashMap;
import java.util.Map;

public class Example_v1 {

     public static void main(String[] args) {
          Map<String, Integer> map = new HashMap<String, Integer>();

          // Insert some sample key-value pairs.
          map.put("Key1", 1);
          map.put("Key2", 2);
          map.put("Key3", 3);

          /* Remove a value of the map, while iterating over it.
           * The following code throws a java.util.ConcurrentModificationException. */
          for(String key: map.keySet()) {
               if(map.get(key) == 1)
                    map.remove(key);
          }
          System.out.println("Successfully removed a pair!");
     }
}

The result of the execution is:

Exception in thread "main" java.util.ConcurrentModificationException
     at java.util.HashMap$HashIterator.nextEntry(HashMap.java:926)
     at java.util.HashMap$KeyIterator.next(HashMap.java:960)
     at main.java.Example.main(Example.java:18)

The exception is thrown because we change the internal structure of the HashMap by removing an existing key, while we iterating over it.

Case 2: After the creation of an iterator, the Collection is internally modified by any method other than the iterator’s own methods for removal and addition.

Example_v2.java:

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

public class Example_v2 {

     public static void main(String[] args) {
          List<String> list = new ArrayList<String>();

          // Insert some sample values.
          list.add("Value1");
          list.add("Value2");
          list.add("Value3");

          // Get an iterator.
          Iterator<String> ite = list.iterator();

          /* Remove the first object of the list. This statement will force the iterator
           * to throw a ConcurrentModificationException. */
          list.remove(0);

          while(ite.hasNext())
               System.out.println(ite.next());
     }
}

The result of the execution is:

Exception in thread "main" java.util.ConcurrentModificationException
     at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
     at java.util.ArrayList$Itr.next(ArrayList.java:831)
     at main.java.Example.main(Example.java:25)

The exception is thrown because:

Case 3: Two iterators simultaneously modify the internal structure of a Collection.

Example_v3.java:

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

public class Example_v3 {

     public static void main(String[] args) {
          List<String> list = new ArrayList<String>();

          // Insert some sample values.
          list.add("Value1");
          list.add("Value2");
          list.add("Value3");

          // Get two iterators.
          Iterator<String> ite = list.iterator();
          Iterator<String> ite2 = list.iterator();

          // Point to the first object of the list and then, remove it.
          ite.next();
          ite.remove();

          /* The second iterator tries to remove the first object as well. The object does
           * not exist and thus, a ConcurrentModificationException is thrown. */
          ite2.next();
          ite2.remove();
     }
}

The result of the execution is:

Exception in thread "main" java.util.ConcurrentModificationException
     at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
     at java.util.ArrayList$Itr.next(ArrayList.java:831)
     at main.java.Example.main(Example.java:28)

The exception is thrown because:

  • We create two iterators of the ArrayList.
  • The 1st iterator modifies the internal structure of the list, by removing its first object.
  • The 2nd iterator tries to remove the first object as well, but the first object does not exist and thus, a ConcurrentModificationException is thrown.

2. Deal with the exception

First of all, we must understand how Java decides that a collection is modified concurrently and a ConcurrentModificationException must be thrown. In Java 7, the implementation of the ArrayList uses the following field, to provide a fail-fast iterator:

protected transient int modCount;

Following the same logic, the implementation of the HashMap uses the following field:

transient int modCount;

In both implementations, the modCount field indicates the number of times the collection has been structurally modified. For example, a structural modification can be an operation that changes the number of mappings in a HashMap, or an operation that changes the size of an ArrayList.

In any case, if the value of the modCount field changes unexpectedly, a ConcurrentModificationException is thrown.

In the rest of this section, we will discuss about techniques and tricks that help us avoid the ConcurrentModificationException:

Iterator’s remove method

In a single-threaded environment, use the iterator’s remove method, in order to concurrently iterate over a collection and remove things from it. For example:

Example_v4.java:

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

public class Example_v4 {

     public static void main(String[] args) {
          List<String> list = new ArrayList<String>();

          // Insert some sample values.
          list.add("Value1");
          list.add("Value2");
          list.add("Value3");

          // Get an iterator.
          Iterator<String> ite = list.iterator();

          /* Remove the second value of the list, while iterating over its elements,
           * using the iterator's remove method. */
          while(ite.hasNext()) {
               String value = ite.next();
               if(value.equals("Value2"))
                    ite.remove();
               else
                    System.out.println(value);
          }
     }
}

Synchronization

In order to avoid more than one threads accessing or modifying the same object, you can synchronize them over the object, in order to allow only one thread to manipulate it over the time. However, notice that this approach may reduce the performance of your application, or create deadlocks, if the application has not been developed carefully.

Synchronized Collections

In addition to their default implementations, Java provides a synchronized implementation of a Map, a List, a Set, a Collection, etc. through the Collections class. Moreover, Java provides the CopyOnWriteArrayList class, in which all mutative operations are implemented by making a fresh copy of the underlying array. Finally, Java also provides the ConcurrentHashMap class, which offers full concurrency of retrievals and adjustable expected concurrency for updates.

All referenced implementations are thread safe. However, the usage of such data structures may also reduce the performance of your application, as thread synchronization spends CPU cycles.

To conclude, all aforementioned methods aim to eliminate the ConcurrentModificationException. However, in a multi-threaded environment this elimination usually comes with the cost of thread synchronization. In any case, each application has its own specifications and requirements and thus, a meticulous design and implementation are very important in order for such exceptions to be eliminated.

3. Download The Eclipse Project

The Eclipse project of this example: ConcurrentModificationExceptionTutorial.zip

 
This was a tutorial on how to handle the ConcurrentModificationException.

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you our best selling eBooks for FREE!

 

1. JPA Mini Book

2. JVM Troubleshooting Guide

3. JUnit Tutorial for Unit Testing

4. Java Annotations Tutorial

5. Java Interview Questions

6. Spring Interview Questions

7. Android UI Design

 

and many more ....

 

Receive Java & Developer job alerts in your Area

 

Leave a Reply

Be the First to Comment!

Notify of
avatar
wpDiscuz