DEV Community

Code Green
Code Green

Posted on • Edited on

2

In Java what is ConcurrentModificationException? How to avoid it in multi-threading. #InterviewQuestion

Problem Statement:

In multi-threaded environments, when multiple threads interact with the same object or collection concurrently, there is a risk of ConcurrentModificationException due to unsynchronized modifications.

Background

ConcurrentModificationException is thrown by List in Java when the collection is structurally modified (e.g., adding or removing elements) during iteration. This is due to the modification count maintained internally by the list, which is checked by iterators to detect concurrent modifications. If the modification count changes unexpectedly, it signals that the collection's structure has been altered concurrently, ensuring safe and consistent iteration behavior.

Solution:

Ensure thread safety by using synchronized blocks or concurrent data structures to manage access and modifications to shared objects or collections.

1. Java ConcurrentModificationException (Without Synchronization)

Example demonstrating ConcurrentModificationException when modifying a collection concurrently without proper synchronization.

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

public class ConcurrentModificationExample{
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(1);
        numbers.add(2);
        numbers.add(3);

        // Thread 1: Iterating and modifying the list
        Thread thread1 = new Thread(() -> {
            Iterator<Integer> iterator = numbers.iterator();
            while (iterator.hasNext()) {
                Integer number = iterator.next();
                System.out.println("Thread 1::value=>"+number);

            }
        });

        // Thread 2: Adding an element to the list concurrently
        Thread thread2 = new Thread(() -> {
            try {
                numbers.add(4);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        thread1.start();
        thread2.start();


        System.out.println("List after modification: " + numbers);
    }
}

/*
Output:
Exception in thread "Thread-0" java.util.ConcurrentModificationException
    at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1043)
    at java.base/java.util.ArrayList$Itr.next(ArrayList.java:997)
    at ConcurrentModificationExample.lambda$main$0(ConcurrentModificationExample.java:16)
    at java.base/java.lang.Thread.run(Thread.java:829)
*/
Enter fullscreen mode Exit fullscreen mode

2. Java ConcurrentModificationException Avoided (With Synchronization)

Example demonstrating how to avoid ConcurrentModificationException by using proper synchronization.


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

public class ConcurrentModificationExample {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(1);
        numbers.add(2);
        numbers.add(3);

        // Thread 1: Iterating and removing elements with proper synchronization
        Thread thread1 = new Thread(() -> {
            synchronized (numbers) {
                Iterator<Integer> iterator = numbers.iterator();
                while (iterator.hasNext()) {
                    Integer number = iterator.next();
                    System.out.println("Thread 1::value=>"+number);

                }
            }
        });

        // Thread 2: Adding an element to the list concurrently
        Thread thread2 = new Thread(() -> {
            synchronized (numbers) {
                    numbers.add(4);

            }
        });

        thread1.start();
        thread2.start();

        System.out.println("List after modification: " + numbers);
    }
}
/*Output:
Thread 1::value=>1
Thread 1::value=>2
Thread 1::value=>3
List after modification: [1, 2, 3, 4]
*/
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • ConcurrentModificationException Example: The first example demonstrates a scenario where Thread 1 attempts to iterate over element s from the list while Thread 2 adds an element concurrently, leading to ConcurrentModificationException due to lack of synchronization.

  • ConcurrentModificationException Avoided Example: The second example shows how to avoid ConcurrentModificationException by using synchronized blocks around critical sections of code where the list is being iterated or modified. This ensures that only one thread accesses the list at a time, preventing concurrent modification issues.

Conclusion:

Implementing proper synchronization techniques such as using synchronized blocks or concurrent data structures from java.util.concurrent package is essential when working with shared mutable data structures in multi-threaded environments. This ensures thread safety and prevents runtime errors like ConcurrentModificationException in Java programs.

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

AWS Security LIVE!

Hosted by security experts, AWS Security LIVE! showcases AWS Partners tackling real-world security challenges. Join live and get your security questions answered.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️