Я смотрю на исходный код ConcurrentHashMap
и удивляюсь, как метод get()
работает без какого-либо монитора, вот код:
public V get(Object key) {
Node<K,V>[] tab; Node<K,V> e, p; int n, eh; K ek;
int h = spread(key.hashCode());
if ((tab = table) != null && (n = tab.length) > 0 &&
(e = tabAt(tab, (n - 1) & h)) != null) {
if ((eh = e.hash) == h) {
if ((ek = e.key) == key || (ek != null && key.equals(ek))) // mark here for possible dirty read
return e.val;
}
else if (eh < 0)
return (p = e.find(h, key)) != null ? p.val : null;
while ((e = e.next) != null) {
if (e.hash == h &&
((ek = e.key) == key || (ek != null && key.equals(ek)))) // mark here for possible dirty read
return e.val;
}
}
return null;
}
Две отмеченные мной строки делают одно и то же : проверка, соответствует ли key
текущего Node<K, V>
необходимому key
. Если true
, вернет соответствующее значение. Но что, если другой поток обрежет до return
и remove()
этот узел из структуры данных. Поскольку локальная переменная e
по-прежнему содержит ссылку на удаленный узел, G C оставит его как есть, а метод get()
по-прежнему вернет удаленное значение, что приведет к неправильному чтению.
Я что-то пропустил?