Да, вы синхронизируете правильно. Я объясню это более подробно.
Вы должны синхронизировать два или более вызовов метода для объекта synchronizedMap только в том случае, если вам нужно полагаться на результаты предыдущих вызовов метода при последующем вызове метода в последовательности вызовов метода объекта synchronizedMap.
Давайте посмотрим на этот код:
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);
}
}
В этом коде
synchronizedMap.get(key).add(value);
и
synchronizedMap.put(key, valuesList);
вызовы метода основаны на результате предыдущего
synchronizedMap.containsKey(key)
вызов метода.
Если последовательность вызовов методов не была синхронизирована, результат может быть неправильным.
Например, thread 1
выполняет метод addToMap()
, а thread 2
выполняет метод doWork()
Последовательность вызовов методов для объекта synchronizedMap
может быть следующей:
Thread 1
выполнил метод
synchronizedMap.containsKey(key)
и результат "true
".
После этого операционная система переключила управление выполнением на thread 2
и выполнила
synchronizedMap.remove(key)
После этого управление выполнением переключается обратно на thread 1
и выполняется, например,
synchronizedMap.get(key).add(value);
полагая, что synchronizedMap
объект содержит key
и NullPointerException
будет брошено, потому что synchronizedMap.get(key)
вернет null
.
Если последовательность вызовов методов для объекта synchronizedMap
не зависит от результатов друг друга, вам не нужно синхронизировать последовательность.
Например, вам не нужно синхронизировать эту последовательность:
synchronizedMap.put(key1, valuesList1);
synchronizedMap.put(key2, valuesList2);
Здесь
synchronizedMap.put(key2, valuesList2);
вызов метода не зависит от результатов предыдущего
synchronizedMap.put(key1, valuesList1);
вызов метода (ему все равно, если какой-то поток вмешался между двумя вызовами метода и, например, удалил key1
).