Home > Software design >  Java ConcurrentModificationException for writing to array list from multiple thread
Java ConcurrentModificationException for writing to array list from multiple thread

Time:08-03

In java I have the following Item class

public class Item {
    private final List<Integer> list = new ArrayList<>();

    public synchronized List<Integer> getList() {
        return list;
    }
}

and I'm accessing list element of this class from multiple threads which is throwing concurrent exception error.

public class Main {

    public static void main(String[] args) {
        Item instance1 = new Item();
        Collections.addAll(instance1.getList(),-1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,-13,-14,-15);

        new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i = 1;i<=25;i  ){
                    instance1.getList().add(i);
                }
                for(int i : instance1.getList()){
                    System.out.println(i  " ");
                }

                thirdPartyLib(instance1.getList());//Third party library which is internally iterating over list
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i = 26;i<=50;i  ){
                    instance1.getList().add(i);
                }
                for(int i : instance1.getList()){
                    System.out.println("from2 " i);
                }

               thirdPartyLib(instance1.getList());//Third party library which is internally iterating over list
            }
        }).start();
    }
}

It is perfectly working with CopyOnWriteArrayList but in real scenario list is being edited many times from multiple places therefore CopyOnWriteArrayList is not the good choice for me. Also I can't use Iterator because this error is thrown by third party library which is working with list. is there any way by which I can solve this error?

CodePudding user response:

There exists Collections.synchronizedList, however you would still need to synchronize on the list when using an Iterator, so the third party lib is problematic.

    new Thread(() -> {
        List<Integer> list = instance1.getList();
        for(int i = 1;i<=25;i  ){
            list.add(i);
        }
        synchronized (list) {
            for(int i : list){
                System.out.println(i  " ");
            }
        }
        synchronized (list) {
            thirdPartyLib(list);//Third party library which is internally iterating over list
        }
    }).start();

    new Thread(() -> {
        List<Integer> list = instance1.getList();
        for(int i = 26;i<=50;i  ){
            instance1.list.add(i);
        }
        synchronized (list) {
            for(int i : list){
                System.out.println("from2 " i);
            }
        }
        synchronized (list) {
            thirdPartyLib(list);//Third party library which is internally iterating over list
        }
    }).start();
}

public class Item {
    private final List<Integer> list = Collections.synchronizedList(new ArrayList<>());

    public List<Integer> getList() {
        return list;
    }
}

This is quite unsatisfactory.

You could combine that CopyOnWriteArrayList and provide independent IntStreams for iterations, best with no List access, just an add method in Item.

  • Related