Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Collections.synchronized map makes Iterator threadsafe

There are two threads in a system. One is a reader thread and another is a writer thread.

The map is synchronized using the following code.

Map<String,ArrayList<String>> m = Collections.synchronizedMap(new HashMap<String,ArrayList<String>())

The reader thread obtains an Iterator on the values of the map and at the same time writer thread modifies the map.

So, my question is will the Iterator throw ConcurrentModificationException?

like image 645
Touchstone Avatar asked Sep 26 '22 11:09

Touchstone


1 Answers

Maybe. It's not safe to do so. The documentation says

It is imperative that the user manually synchronize on the returned map when iterating over any of its collection views

Collections.synchronized... makes single method calls atomic so they don't need further synchronization. But iteration is more than a single method call so it needs extra synchronization. Below is an example

    Map<String, String> shared = Collections.synchronizedMap(new HashMap<>());

    new Thread(() -> {
        while (true) {
            synchronized (shared) {
                for (String key : shared.keySet()) {
                    System.out.println(key);
                }
            }
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
                break;
            }
        }
    }).start();

    new Thread(() -> {
        while (true) {
            try {
                // this is atomic
                shared.put(UUID.randomUUID().toString(), "Yo!");
                Thread.sleep(1000);
            } catch (Exception e) {
                break;
            }
        }
    }).start();
}
like image 60
zapl Avatar answered Oct 13 '22 21:10

zapl