Выбор ответа Middle java.util.concurrent и виртуальные потоки спрашивают часто обновлено
Гонка на ConcurrentHashMap
Вопрос
Код if (!cache.containsKey(k)) cache.put(k, load(k)); выполняется в нескольких потоках, cache это ConcurrentHashMap. Что не так?
Попробуйте сами
Выберите вариант, и откроется разбор.
Показать ответ и разбор
Коротко
Правильный ответ: Check-then-act не атомарен: load вызовут дважды; нужен computeIfAbsent. Каждая операция ConcurrentHashMap потокобезопасна по отдельности, но между containsKey и put другой поток успевает сделать то же самое. computeIfAbsent выполняет вычисление атомарно для ключа.
Варианты ответа
- Check-then-act не атомарен:
loadвызовут дважды; нуженcomputeIfAbsentправильный ответ - Ничего: ConcurrentHashMap сам делает такую пару вызовов атомарной
- Будет ConcurrentModificationException, если два потока вставят одно
- Будет дедлок, потому что
putблокирует всю карту на время вызоваload
Разбор
Каждая операция ConcurrentHashMap потокобезопасна по отдельности, но между containsKey и put другой поток успевает сделать то же самое. computeIfAbsent выполняет вычисление атомарно для ключа. CME concurrent-коллекции не бросают. put блокирует только одну корзину, не всю карту.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.