Это добавляет двойную проверку блокировки, семантика транзакции остается прежней;так что это не неправильно .
Является ли это на самом деле оптимизацией, зависит от использования.Мы всегда испытываем искушение проверить в особых случаях, что мы знаем, что существуют более дешевые решения
if A
cheapSolutionForA();
else
genericSolution();
Это может сработать или нет - если A
редко true
, дополнительная проверка обходится дороже, чем экономит.(и когда A действительно иногда имеет значение true, это может нарушить предсказание ветвления ЦП, было бы дешевле всегда использовать универсальное решение, даже когда A = true)
В примере Джошуа, A
действительноправда часто.Он должен запрашивать внутреннюю строку для одной и той же строки (одинаковой по значению, а не по идентичности) много раз, поэтому в большинстве вызовов карта уже имеет ключ.
Если каждый вызов intern()
получает различную строку, то у карты никогда не будет ключа, и его оптимизационные обратные выстрелы - «оптимизация» стоит больше времени и не экономит ни одного.
ИзКонечно, когда дело доходит до строкового интерна, 1-й случай более реалистичен на практике.
В целом, хотя putIfAbsent()
не может предсказать, как он используется, поэтому неразумно включать этот специальный случай "оптимизация" внутриЭто.Во многих случаях использования конкуренция низкая, карта, скорее всего, не имеет ключа при вызове putIfAbsent
, в этих случаях было бы неправильно, если встроена «оптимизация».