Java ArrayList - есть ли вызовы add() из одного потока, всегда читаемого из другого?

Thread 1: Call list.add()
Thread 1: Exits list.add()
Thread 2: Call list.get(list.size()-1)

У меня есть сценарий, где я могу гарантировать, что Thread 1 завершит вызов add() до Thread 2, сделав вызов get(). Будет ли Thread 2 всегда видеть изменения, сделанные Thread 1 в этом случае? Или внутренние переменные ArrayList должны быть отмечены как изменчивые?

Изменить: Для тех, кому интересно, почему я могу это гарантировать. У меня есть последовательность событий с сервера, которые выглядят следующим образом:

Event A1
Event A2
Event A3
Event B

События отправляются последовательно одним потоком. Я хочу записать список всех событий A, чтобы мой код выглядел следующим образом:

List<EventA> eventAList = new ArrayList<>();
connection.addListenerForEventAs(eventAList::add);

connection.waitForEventB();

//Here I am doing operations on the eventAList

Ответы

Ответ 1

Прежде всего, вам нужно будет убедиться, что происходит до того, как существует связь между вызовом add() по потоку-1 и вызовом get() по потоку-2. Завершение вызова и происходит до этого совершенно разные.

Если вы этого не сделаете, ваш код не будет потокобезопасным. Зачем?. Thread-1 может завершить вызов до add() перед вызовом thread-2 get(). Но какова гарантия того, что Thread-2 не сделает локальную копию списка (сохраните его)?. add() метод не гарантирует, что произойдет раньше. Таким образом, нет никакой гарантии, что добавленная стоимость первого потока даже полностью написана и видна для потока-2.

Используйте CopyOnWriteArrayList или Collections.SynchronizedList() в многопоточной среде.

Ответ 2

Используйте Collections.SynchronizedList() в list или ключевое слово, синхронизированное с выделенной реализацией для добавления для обеспечения безопасности потоков,

public synchronized void addItem(Item item) {
    list.add(item);
}