Атомность комбинированного putIfAbsent и заменить на ConcurrentMap
Это относится к принятому решению вопроса, поднятого в этой теме
public void insertOrReplace(String key, String value) {
for (;;) {
String oldValue = concurrentMap.putIfAbsent(key, value);
if (oldValue == null)
return;
final String newValue = recalculateNewValue(oldValue, value);
if (concurrentMap.replace(key, oldValue, newValue))
return;
}
}
Я хотел бы полностью понять код.
я верю putIfAbsent
а также replace
в целом можно рассматривать как сложную операцию. Является ли эта составная операция атомарной без явной синхронизации объекта oldValue
? Или просто из-за for
кругом, это гарантирует атомность? Что именно делает цикл? Будет ли это вызвать бесконечный цикл, который делает метод никогда не заканчивается?
1 ответ
Прежде всего, оригинальный вопрос вводит несколько странный код. Не уверен, что это хорошо, но давайте оставим это в стороне.
Во-вторых, выбранный ответ и тот, который вы скопировали здесь, это просто другой способ сделать тот же код, что и в вопросе.
Итак, что делает этот (причудливый) метод:
- Проверяет, сопоставлен ли ключ значению, а если нет, присваивает значение и существует.
- Если это так, пересчитайте значение и замените старое значение.
Зачем нам тогда петля? Причина, если 2 потока пересчитывают значение и выполняют замену "вместе", только 1 будет успешным и, следовательно, вернется из метода. "Потерявший" поток должен будет снова пройти процесс. Вероятно, получит новое значение в putIfAbsent
вызов и будет пересчитать новое значение, которое будет заменено, на этот раз может быть в порядке.
Несколько вещей, на которые стоит обратить внимание:
- Я бы рекомендовал внимательно прочитать API
ConcurrentMap
"sputIfAbsent
а такжеreplace
методы. - Существует угловой случай (который никогда не случится в действительности), что вызов этого метода будет зависать навсегда, потому что он всегда будет "проигрывать" другому вызову.
- Я подозреваю, что синхронизация всего этого метода будет лучше избегать всех этих громоздких циклов. Но так как я не до конца осознаю, что этот код призван решить, я не могу официально заявить об этом.