2

I'm modifying same list from multiple threads, shouldn't it trigger ConcurrentModificationException while iterating list?

What could be done to trigger this exception?

public class ConcurrentTest {

    static List<String> list = setupList();

    public static List<String> setupList() {
        System.out.println("setup predefined list");

        List<String> l = new ArrayList();
        for(int i = 0; i < 50;i++) {
            l.add("test" + i);
        }

        return l;
    }

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(50);

        for(int i = 0; i < 50; i++) {
            executorService.submit( () -> {     
                list.add("key1");       

                Thread currentThread = Thread.currentThread();
                System.out.println( Thread.currentThread().getName() + ", " + list.size() );

                for(String val: list) {
                    try {
                        Thread.sleep(25);
                    }
                    catch(Exception e) {

                    }
                }

            });
        }

        executorService.shutdown();
    }
}
Xades
  • 23
  • 2

3 Answers3

1

The ConcurrentModificationException triggers when you modify a list while iterating on it. In your code qhen you iterate on the list, you only sleep the thread and do not modify it.This would trigger the exception:

for(String s: list) {
    list.add("something");
}
PauMAVA
  • 1,163
  • 14
  • 23
1

Have you check whether below block throwing exception or not.

try {
    list.add("key1");       

    Thread currentThread = Thread.currentThread();
    System.out.println( Thread.currentThread().getName() + ", " + list.size() );

    for(String val: list) {
        try {
            Thread.sleep(25);
        }
        catch(Exception e) {

        }
    }
}catch (Exception e) {
    e.printStackTrace();
}

Please wrap around try...catch block and print() error message to check its throwing error or not.

mcacorner
  • 1,304
  • 3
  • 22
  • 45
0

Your code does (and can) produce a ConcurrentModificationException. You are not catching it to print it.

With the below, we can see that it indeed throws many ConcurrentModificationException.

try {
    for (String val : list) {
        try {
          Thread.sleep(25);
        } catch (Exception e) {
        }
    }
} catch (Exception e) {
    e.printStackTrace();
}

NOTE: From the javadoc,

Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw {@code ConcurrentModificationException} on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs

Also see: java.util.ConcurrentModificationException not thrown when expected


Or, you could get the returned Future and collect them in a list. By doing that, you will get the exception when calling get on (atleast) one of the futures.

Thiyagu
  • 17,362
  • 5
  • 42
  • 79