Search code examples
javamultithreadingsynchronized

Calling toArray() on a synchronized array list a thread safe operation?


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 ?


Solution

  • 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();}
    }