Search code examples
javaconcurrencyjava.util.concurrent

Java ArrayList - Are add() calls from one thread always readable from another?


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

I have a scenario where I can guarantee that Thread 1 will complete the add() call before Thread 2 make the get() call. Will Thread 2 always see the changes made by Thread 1 in this case? Or would the internal ArrayList variables need to be marked as volatile?

Edit: For those who are curious about why I can guarantee it. I have a sequence of events from a server that look like this:

Event A1
Event A2
Event A3
Event B

The events are dispatched sequentially by a single thread. I want to capture a list of all the A events so my code looks like this:

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

connection.waitForEventB();

//Here I am doing operations on the eventAList

Solution

  • First of all, you will have to ensure that a happens before relationship exists between call of add() by thread-1 and call to get() by thread-2. Completion of call and happens before are totally different.

    Unless you do that, your code will not be thread-safe. Why?. Thread-1 might finish the call to add() before thread-2 calls get(). But what is the guarantee that Thread-2 will not make a local copy of the list (keep it handy)?. add() method doesn't ensure a happens-before. So, there is no guarantee that the value added by the first thread is even written completely and is visible to thread-2 .

    Use CopyOnWriteArrayList or Collections.SynchronizedList() in Multi-threaded environment.