Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Потокобезопасность ArrayList
Стандартный ArrayList
Нет, обычный ArrayList НЕ является потокобезопасным. Если несколько потоков одновременно обращаются к ArrayList и хотя бы один из них модифицирует список, это может привести к ConcurrentModificationException или потере данных.
Проблема
ArrayList использует простой динамический массив без синхронизации:
public class ArrayList<E> {
private Object[] elementData;
private int size;
public boolean add(E e) {
// Нет синхронизации — опасно в многопоточной среде
int oldCapacity = elementData.length;
if (size >= oldCapacity) {
// Увеличение капасити
}
elementData[size++] = e;
return true;
}
}
Если два потока одновременно вызывают add(), они могут перезаписать друг друга значения.
Решения для потокобезопасности
1. Collections.synchronizedList()
Оборачивает ArrayList в синхронизированную обёртку:
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
syncList.add("item");
Каждый метод синхронизирован, но медленнее из-за блокировок.
2. CopyOnWriteArrayList
Оптимизирован для чтения (потокобезопасен по умолчанию):
List<String> copyList = new CopyOnWriteArrayList<>();
copyList.add("item");
При записи создаёт копию массива. Идеален для частого чтения, редкой записи.
3. Явная синхронизация
Для большей гибкости:
List<String> list = new ArrayList<>();
synchronized(list) {
list.add("item");
list.remove(0);
}
Выбор подхода
- CopyOnWriteArrayList — много читателей, мало писателей
- Collections.synchronizedList() — равномерная нагрузка
- Явная синхронизация — сложная логика с несколькими операциями
- concurrent коллекции (ConcurrentHashMap для других сценариев) — высокая параллелизм
ConcurrentModificationException
Если попытаться изменять список во время итерации:
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
for (String item : list) {
if (item.equals("A")) {
list.remove(item); // ConcurrentModificationException!
}
}
Даже в однопоточном коде! Это ещё одна проблема ArrayList.
Вывод
ArrayList в многопоточной среде требует либо внешней синхронизации, либо использования специализированных потокобезопасных коллекций из пакета java.util.concurrent.