← Назад к вопросам

Существует ли потокобезопасный ArrayList

1.0 Junior🔥 251 комментариев
#Коллекции

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Потокобезопасность 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.

Существует ли потокобезопасный ArrayList | PrepBro