Обратите внимание, что во многих ответах говорится, что Hashtable синхронизирован. На практике это очень мало для вас. Синхронизация по методам доступа / мутатора остановит одновременное добавление или удаление двух потоков из карты, но в реальном мире вам часто потребуется дополнительная синхронизация.
Очень распространенная идиома - «проверить, затем положить» - то есть найти запись в Map
и добавить ее, если она еще не существует. Это ни в коем случае не атомарная операция, используете ли вы Hashtable
или HashMap
.
Эквивалентно синхронизированный HashMap
может быть получен:
Collections.synchronizedMap(myMap);
Но для правильной реализации этой логики вам потребуется дополнительная синхронизация вида:
synchronized(myMap) {
if (!myMap.containsKey("tomato"))
myMap.put("tomato", "red");
}
Даже перебор записей Hashtable
(или HashMap
, полученных с помощью Collections.synchronizedMap
) не является потокобезопасным, если вы также не защитите Map
от изменения посредством дополнительной синхронизации.
Реализации интерфейса ConcurrentMap
(например, ConcurrentHashMap
) решают некоторые из этих проблем, включая потокобезопасную семантику проверки-затем-действия , такую как:
ConcurrentMap.putIfAbsent(key, value);