Is the following code set up to correctly synchronize the calls on synchronizedMap?
public class MyClass {
private static Map
Yes, you are synchronizing correctly. I will explain this in more detail. You must synchronize two or more method calls on the synchronizedMap object only in a case you have to rely on results of previous method call(s) in the subsequent method call in the sequence of method calls on the synchronizedMap object. Let’s take a look at this code:
synchronized (synchronizedMap) {
if (synchronizedMap.containsKey(key)) {
synchronizedMap.get(key).add(value);
}
else {
List valuesList = new ArrayList();
valuesList.add(value);
synchronizedMap.put(key, valuesList);
}
}
In this code
synchronizedMap.get(key).add(value);
and
synchronizedMap.put(key, valuesList);
method calls are relied on the result of the previous
synchronizedMap.containsKey(key)
method call.
If the sequence of method calls were not synchronized the result might be wrong.
For example thread 1 is executing the method addToMap() and thread 2 is executing the method doWork()
The sequence of method calls on the synchronizedMap object might be as follows:
Thread 1 has executed the method
synchronizedMap.containsKey(key)
and the result is "true".
After that operating system has switched execution control to thread 2 and it has executed
synchronizedMap.remove(key)
After that execution control has been switched back to the thread 1 and it has executed for example
synchronizedMap.get(key).add(value);
believing the synchronizedMap object contains the key and NullPointerException will be thrown because synchronizedMap.get(key)
will return null.
If the sequence of method calls on the synchronizedMap object is not dependent on the results of each other then you don't need to synchronize the sequence.
For example you don't need to synchronize this sequence:
synchronizedMap.put(key1, valuesList1);
synchronizedMap.put(key2, valuesList2);
Here
synchronizedMap.put(key2, valuesList2);
method call does not rely on the results of the previous
synchronizedMap.put(key1, valuesList1);
method call (it does not care if some thread has interfered in between the two method calls and for example has removed the key1).