Search code examples
javaconcurrencyjava.util.concurrentreadwritelockcopyonwritearraylist

How to replace a non-synchronized concurrent list or array atomically


I have a List read (iterated through) many times and by multiple threads but updated rarely (reads are more than 50,000 times more numerous). EDIT: in fact, an array would suffice in this case, instead of a List.

When the list is updated, it's simply replaced with a different version (there are no add() or remove() calls).

A CopyOnWriteArrayList avoid the disadvantages of a synchronized list but I'm not sure that setting the list to the new value is atomic. I read this question as well.

To show some code. Consider the following as an attribute of a singleton Spring bean.

List<MyObject> myList; //the list read many times and concurrently. 

//called by many threads
public void doStuff(){           
     for (MyObject mo : myList){
         //do something
     }
}       

//called rarely. It's synchronized to prevent concurrent updates
//but my question is about thread-safety with regards to readers
public synchronized void updateList(List<MyObject> newList){  // newList is a CopyOnWriteArrayList<>(); 
    myList = myNewList;  //is this following statement executed atomically and thread-safe for readers?
}

Do I need to use a ReadWriteLock for achieve a thread-safe set?


Solution

  • The need for ReadWriteLock depends what you need to achieve. If you want to ensure that reference is updated atomically you can use AtomicReference (or in your case enough to mark this reference as volatile), however if your goal is that updater thread should wait until all reading threads finish iterating over old list before updating the reference then ReadWriteLock is the way to go.