ConcurrentModificationException в java
Пробовал найти статьи в интернете, но, в основном, там речь идёт о том, как с этим бороться. Хотелось бы получить базовые знания о том, что это, в каких ситуациях возникает, как избежать и т.д.
Ответы (1 шт):
Один кусок кода дороже тысячи слов...
Если вам интересно, в каких ситуациях возникает, посмотрите в исходниках. Например, 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. Если не найдёт, то скрестить пальцы и верить, что коллизий не будет :)