exceptions

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

The java.util.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 java.util.concurrentmodificationexception when they detect such behavior. These iterators are called fail-fast iterators, as they stop the normal execution to report an error, rather than 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 java.util.concurrentmodificationexception.

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

Example_v1.java:

java.util.concurrentmodificationexception
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:

  • We create an iterator of the ArrayList.
  • We remove an object using the remove method, rather than the iterator’s own remove method.
  • We try to iterate over the list and thus, a java.util.concurrentmodificationexception is thrown.

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 java.util.concurrentmodificationexception 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 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 thread accessing or modifying the same object, you can synchronize them over the object, in order to allow only one thread to manipulate it over 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

This was a tutorial on how to handle the ConcurrentModificationException.

Download
You can download the full source code of this example here: java.util.concurrentmodificationexception – How to handle Concurrent Modification Exception

Last updated on Dec. 09th, 2021

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.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Pedro Barcellos
4 years ago

Thanks man, you saved me!

Back to top button