Я пытаюсь просмотреть исходный код Spring (5.2.8.RELEASE) и нашел следующий код.
package org.springframework.core;
public class SimpleAliasRegistry implements AliasRegistry {
/** Map from alias to canonical name. */
private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);
@Override
public void removeAlias(String alias) {
synchronized (this.aliasMap) { // what if we remove such synchronized line ?
String name = this.aliasMap.remove(alias);
if (name == null) {
throw new IllegalStateException("No alias '" + alias + "' registered");
}
}
}
}
Но что я не уверен, так это причина, по которой в методе removeAlias есть ключевое слово synchronized, действительно ли это необходимо? Что, если мы удалим синхронизированное ключевое слово? Что случится?
Вот моя мысль. ConcurrentHashMap
должен быть потокобезопасным, когда мы вызываем его предоставленный метод, например put
, get
и remove
. И нам нужно использовать synchronized
для блокировки объекта только тогда, когда мы выполняем здесь несколько действий, например сначала получаем, а затем помещаем или удаляем. Но мы хотим, чтобы блок работал без перерыва.
Моя мысль неверна, или есть какая-то причина, по которой метод Spring removeAlias
разработан таким образом, большое спасибо.
Обновлять
Еще нашел время, когда он обновляется, где разработчик намеренно так делает, при исправлении проблемы, SimpleAliasRegistry registerAlias not atomic
, и вот причину выписал.
Я защитил registerAlias и removeAlias синхронизацией, позволяя существующему синхронизированному методу resolveAliases и другим надежно видеть согласованное состояние.
Тем не менее, я просто думаю, что синхронизация в registerAlias необходима, но все же не убеждаю, почему нужно делать synchronized
в методе removeAlias, может кто-нибудь объяснить мне, пожалуйста?
Источник: https://github.com/spring-projects/spring-framework/issues/21119 [выпуск]
Источник: https://github.com/spring-projects/spring-framework/commit/1b1a69a144f657d46c752f1c017f64d3302891d2 [Изменения для этой проблемы]
ConcurrentHashMap
обычно не нуждается в такой блокировке, но не забывайте, что программисту может понадобиться заблокировать этот объект в какой-то другой части кода. Или программист ошибся. Такое случается. - person markspace   schedule 06.07.2021aliasMap
объявляется какMap
, а не какConcurrentMap
. Я подозреваю, что этот код изначально был написан, не думая об использовании параллельного экземпляра карты, отсюда иsynchronized
для управления параллелизмом. Разработка Spring была начата до выпуска Java 5, который принесConcurrentMap
иConcurrentHashMap
в 2004 году. Но мой комментарий здесь - все дикие предположения, у меня нет реальных знаний. - person Basil Bourque   schedule 06.07.2021