Атомность комбинированного 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 ответ

Решение

Прежде всего, оригинальный вопрос вводит несколько странный код. Не уверен, что это хорошо, но давайте оставим это в стороне.

Во-вторых, выбранный ответ и тот, который вы скопировали здесь, это просто другой способ сделать тот же код, что и в вопросе.

Итак, что делает этот (причудливый) метод:

  1. Проверяет, сопоставлен ли ключ значению, а если нет, присваивает значение и существует.
  2. Если это так, пересчитайте значение и замените старое значение.

Зачем нам тогда петля? Причина, если 2 потока пересчитывают значение и выполняют замену "вместе", только 1 будет успешным и, следовательно, вернется из метода. "Потерявший" поток должен будет снова пройти процесс. Вероятно, получит новое значение в putIfAbsent вызов и будет пересчитать новое значение, которое будет заменено, на этот раз может быть в порядке.

Несколько вещей, на которые стоит обратить внимание:

  1. Я бы рекомендовал внимательно прочитать API ConcurrentMap"s putIfAbsent а также replace методы.
  2. Существует угловой случай (который никогда не случится в действительности), что вызов этого метода будет зависать навсегда, потому что он всегда будет "проигрывать" другому вызову.
  3. Я подозреваю, что синхронизация всего этого метода будет лучше избегать всех этих громоздких циклов. Но так как я не до конца осознаю, что этот код призван решить, я не могу официально заявить об этом.
Другие вопросы по тегам