Ryan Ahearn Ryan Ahearn - 3 months ago 22
Java Question

Java synchronized block vs. Collections.synchronizedMap

Is the following code set up to correctly synchronize the calls on

synchronizedMap
?

public class MyClass {
private static Map<String, List<String>> synchronizedMap = Collections.synchronizedMap(new HashMap<String, List<String>>());

public void doWork(String key) {
List<String> values = null;
while ((values = synchronizedMap.remove(key)) != null) {
//do something with values
}
}

public static void addToMap(String key, String value) {
synchronized (synchronizedMap) {
if (synchronizedMap.containsKey(key)) {
synchronizedMap.get(key).add(value);
}
else {
List<String> valuesList = new ArrayList<String>();
valuesList.add(value);
synchronizedMap.put(key, valuesList);
}
}
}
}


From my understanding, I need the synchronized block in
addToMap()
to prevent another thread from calling
remove()
or
containsKey()
before I get through the call to
put()
but I do not need a synchronized block in
doWork()
because another thread cannot enter the synchronized block in
addToMap()
before
remove()
returns because I created the Map originally with
Collections.synchronizedMap()
. Is that correct? Is there a better way to do this?

Answer

Collections.synchronizedMap() guarantees that each atomic operation you want to run on the map will be synchronized.

Running two (or more) operations on the map however, must be synchronized in a block. So yes - you are synchronizing correctly.