Blog |

How to Avoid the Concurrent Modification Exception in Java

How to Avoid the Concurrent Modification Exception in Java
Table of Contents
Try Rollbar Today

Proactively discover and resolve errors

The ConcurrentModificationException is a very common exception in Java that occurs usually while working with Collections. The ConcurrentModificationException is used to fail-fast when something being iterated on is modified.

This exception occurs when an object is attempted to be modified concurrently without permission. For example, if a Collection is modified while a thread is traversing it using an Iterator, a ConcurrentModificationException is thrown from the Iterator.next() method.

The ConcurrentModificationException can occur in both multithreaded and single-threaded environments.

 

What Causes ConcurrentModificationException

The ConcurrentModificationException generally occurs when working with Java Collections. The Collection classes in Java are very fail-fast and if they are attempted to be modified while a thread is iterating over it, a ConcurrentModificationException is thrown.

This exception can occur in both multithreaded and single-threaded Java environments. Here are examples of each:

  • Multithreaded environment - If a thread is traversing over a Collection using an Iterator and another thread attempts to add or remove elements to the Collection.
  • Single-threaded environment - When an element is attempted to be removed from an ArrayList using the remove() method while it is being traversed using an enhanced for loop.

 

ConcurrentModificationException Example

Here is an example of a ConcurrentModificationException thrown when attempting to remove an element from an ArrayList using the remove() method while traversing it using an enhanced for loop:

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

public class ConcurrentModificationExceptionExample {
    public static void main(String args[]) {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");

        for (String elem : list) {
            if (elem.equals("a")) {
                list.remove(elem);
            }
        }
    }
}

Since the enhanced for loop uses an Iterator internally to traverse elements in a Collection, running the above code causes a ConcurrentModificationException since the remove() method of the Collection is used instead of the iterator:

Exception in thread "main" java.util.ConcurrentModificationException
    at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1013)
    at java.base/java.util.ArrayList$Itr.next(ArrayList.java:967)
    at ConcurrentModificationExceptionExample.main(ConcurrentModificationExceptionExample.java:12)

 

How to Resolve ConcurrentModificationException

The above exception can be resolved by traversing the elements of the ArrayList using a traditional for loop instead of the enhanced for loop. Since the traditional for loop does not use an Iterator to traverse the elements of a Collection, it does not cause a ConcurrentModificationException:

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

public class ConcurrentModificationExceptionExample {
    public static void main(String args[]) {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");

        for (int i = 0; i < list.size(); i++) {
            if (list.get(i).equals("a")) {
                list.remove(list.get(i));
            }
        }

        System.out.println(list);
    }
}

Since the ConcurrentModificationException belongs to the Iterator and not the remove() method of the ArrayList, running the above code will produce the correct output as expected:

[b, c, d]

The above exception can also be resolved by using an Iterator to traverse the elements of the ArrayList and using the Iterator.remove() method to remove elements. Alternatively, the Collection.removeIf() method introduced in Java 8 can be used to remove an element from a Collection if a given condition is true.

 

How to Avoid ConcurrentModificationException in Multithreaded Environments

To avoid the ConcurrentModificationException in multithreaded environments, certain precautions can be used:

  • Iterating over an array instead of a collection - this can work well with small-sized lists but can degrade performance for larger ones.
  • Locking the collection by placing it in a synchronized block - this may not be the most effective approach as it does not utilize the very purpose of multi-threading.
  • Using Java concurrent collections such as ConcurrentHashMap and CopyOnWriteArrayList classes can help avoid the ConcurrentModificationException.

 

Track, Analyze and Manage Errors with Rollbar

Rollbar in action

Fixing Errors in your Java code is challenging. It can make deploying production code an unnerving experience. Being able to track, analyze, and manage errors in real-time can help you to proceed with more confidence. Rollbar automates error monitoring, tracking and triaging, making fixing Java errors easier than ever. Sign Up Today!

Related Posts

See all posts

"Rollbar allows us to go from alerting to impact analysis and resolution in a matter of minutes. Without it we would be flying blind."

Start continuously improving your code today.

Get Started Shape