Нет, эта конструкция не является поточно-ориентированной.
Предположим, что нить writer
помещает что-то в карту, а размер карты слишком мал, поэтому ее размер нужно изменить.Это делается внутри блока synchronized
, поэтому вы можете думать, что у вас все хорошо.
Во время изменения размера ничто на карте не гарантируется.
Теперь, в то же самое время, предположим,что поток reader
вызывает getStuff
для существующего элемента.Этот поток может получить прямой доступ к карте, поскольку он не попадает в блок synchronized
при первом вызове containsKey
и get
.Он найдет карту в неопределенном состоянии и, хотя он только читает, он получает доступ к данным, содержимое которых не определено.Среди возможных результатов:
getStuff
возвращает null
, когда это не должно быть. getStuff
возвращает ожидаемое Stuff
. getStuff
возвращает некоторый внутренний объект, который используется реализацией HashMap
во время изменения размера. getStuff
возвращает некоторый другой Stuff
, не связанный с именем. getStuff
попадаетв бесконечном цикле.
Это просто очевидный случай, который должен быть прост для понимания.Так что нет, не используйте ярлыки, когда есть хорошо разработанные классы, такие как ConcurrentHashMap
или Guava's MapMaker
.
Кстати: Звоните containsKey
сначала, а потом get
с тем же ключом довольно неэффективно.Просто позвоните get
, сохраните результат и сравните его с null
.Вы сохраните одну поисковую операцию на карте.