Модифицируя ArrayList с одним потоком и повторяя его с другим потоком, он создает исключение ConcurrentModificationException

Я пытался ниже кода.

public class IteratorFailFastTest {

    private List<Integer> list = new ArrayList<>();

    public IteratorFailFastTest() {
        for (int i = 0; i < 10; i++) {
            list.add(i);
        }
    }

    public void runUpdateThread() {
        Thread thread2 = new Thread(new Runnable() {

            public void run() {
                for (int i = 10; i < 20; i++) {
                    list.add(i);

                }
            }
        });

        thread2.start();
    }


    public void runIteratorThread() {
        Thread thread1 = new Thread(new Runnable() {

            public void run() {
                ListIterator<Integer> iterator = list.listIterator();

                while (iterator.hasNext()) {
                Integer number = iterator.next();
                System.out.println(number);
                }

            }
        });

        thread1.start();
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        IteratorFailFastTest tester = new IteratorFailFastTest();

        tester.runIteratorThread();
        tester.runUpdateThread();
    }

}

Иногда выбрасывает ConcurrentModificationException, а иногда и успешно.

Чего я не понимаю, так это 2 разных метода, каждый из которых содержит один поток. Они будут выполнять по одному. Когда один поток завершит изменение списка, поток 2 начнет итерацию.

Я также ссылался на эту ссылку ( почему нет ConcurrentModificationException, когда один поток повторяется (используя Iterator), а другой поток изменяет одну и ту же копию не-поточно-безопасного ArrayList), но это другой сценарий.

Так почему же это исключение? Это из-за потоков?

Может кто-нибудь объяснить?

1 ответ

Вы запускаете два потока, а затем не выполняете дальнейшую синхронизацию.

Иногда оба потока будут работать одновременно, и вы получите CME. В других случаях первый поток завершается до того, как второй поток фактически начнет выполняться. В этом случае не получит CME.

Причина, по которой вы получаете этот вариант, может быть связана с нагрузкой на вашу систему. Или это может быть просто из-за того, что планировщик потока недетерминирован.

Ваши потоки фактически выполняют небольшую работу по сравнению с накладными расходами на создание / запуск потока. Поэтому неудивительно, что один из них может вернуться из своего run() метод очень быстро.

Другие вопросы по тегам