Это интересный вопрос.
Правильный ответ:
Существует несколько реалистичных случаев, когда последовательность операций get и put для ConcurrentHashMap
даст ожидаемый результат в многопоточном сценарии. Вместо put()
вам почти всегда нужно использовать атомарные операции сравнения и изменения , такие как computeIfAbsent()
, чтобы сделать что-нибудь полезное. Единственным исключением является случай, когда вы используете карту в качестве кэша, и возможность того, чтобы несколько потоков вычисляли одну и ту же запись, более эффективна, чем блокировка, пока один поток делает это ... но тогда вам действительно нужен кэш? Не очень часто.
Только для записи, это выглядело бы так:
Thread1 + Thread2 (they both do the same thing)
-----------------------------------------------
result = map.get(key);
if (result == null) {
result = somewhat_expensive_function(key)
map.put(key, result);
}
return result;
С другой стороны, использование нормального HashMap
в двух потоках, когда один может изменять карту, в то время как другой также использует ее, может привести к неопределенному поведению - результаты не согласуются с какой-либо последовательностью операций, исключениями являются нулевые указатели или даже полностью поврежденная структура данных.
Если бы я задал этот вопрос в интервью, я бы протестировал следующее: понимает ли кандидат, что использование потоковых структур данных не делает его алгоритм поточно-безопасным?