ConcurrentModificationException в java

Пробовал найти статьи в интернете, но, в основном, там речь идёт о том, как с этим бороться. Хотелось бы получить базовые знания о том, что это, в каких ситуациях возникает, как избежать и т.д.


Ответы (1 шт):

Автор решения: Pak Uula

Один кусок кода дороже тысячи слов...

Если вам интересно, в каких ситуациях возникает, посмотрите в исходниках. Например, java.util.ArrayList и java.util.AbstractList

Если коротко, то у каждого объекта типа AbstractList есть счётчик modCount. Каждая операция, которая изменяет список, такие как добавление элементов, удаление элементов, очистка списка, и т.п., этот счетчик инкрементирует.

Те операции, которым нужно, чтобы список в ходе выполнения операции не менялся, например операция equals, сохраняют значение modCount до начала выполнения операции, и в конце операции обязательно сравнивают с текущим значением modCount. Если значения не совпали, то выбрасывается ConcurrentModificationException.

Самый простой пример - вычисление хэш-кода:

    public int hashCode() {
        int expectedModCount = modCount;
        int hash = hashCodeRange(0, size);
        checkForComodification(expectedModCount);
        return hash;
    }

Метод checkForComodification выбросит исключение, если текущее значение modCount не совпадёт с expectedModCount.

Поищите по тексту классов выражение modCount++ - вы найдёте все те места, в которых меняется состояние объекта. Все те места, где ожидается неизменность объекта в ходе выполнения операции, содержат вызов checkForComodification.

Как избежать?

Простой, но дорогой в эксплуатации способ - обернуть все операции с коллекцией в RWLock. Сложный и недостоверный способ - прогнать вашу программу через статический анализатор и поискать race conditions. Если не найдёт, то скрестить пальцы и верить, что коллизий не будет :)

→ Ссылка