I am creating and using a synchronized array list which is being accessed/modified by multiple threads. In a certain operation I want to remove all elements of this synchronized list and process them.
List<String> myList = Collections.synchronizedList(new ArrayList<>());
// adding to array
public void addElements(String s) {
myList.add(s)
}
public void removeAllAndProcess() {
Arrays.stream(myList.toArray()).forEach(s -> {
myList.remove(s);
process(s.toString());
});
}
// Some processing
public void process(String s) {
// if processing unsuccessful then again add to list : myList.add(s)
}
I am wondering if toArray()
needs to be within a synchronized block ? Will a concurrent addition to the list while toArray
is being called will affect the returned array ?
No additional synchronisation is needed as Collections.synchronizedList(xyz)
wraps all access to underlying xyz
safely.
You could double check your JDK implementation by following the source code in a good IDE. In OpenJDK20 you will see that Collections.synchronizedList
returns a SynchronizedList
public static <T> List<T> synchronizedList(List<T> list) {
return (list instanceof RandomAccess ?
new SynchronizedRandomAccessList<>(list) :
new SynchronizedList<>(list));
}
SynchronizedList
extends SynchronizedCollection
which implements toArray()
with object synchronisation to ensure that you have thread-safe operation:
public Object[] toArray() {
synchronized (mutex) {return c.toArray();}
}