2016-10-27 3 views
1

Как я понимаю, put(), clear() и remove() обеспечиваются ConcurrentHashMap и это нить безопасной работы без использования каких-либо замков.ConcurrentHashMap удалить() с использованием нити А в то время как итерация с помощью резьбы B

В ConcurrentHashMap есть разные сегменты, и для каждого сегмента есть несколько хэш-ковшей.

Clear() и put() потокобезопасны потому что clear() просто очистить ссылку на хэш-цепочку для этого ведра, но хэш-цепи по-прежнему существует, так что если поток А итерация над ним, это не повлияет, но clear() от нить B. Put() всегда будет устанавливать новый узел в начале хэш-цепочки для этого ведра, так что это тоже хорошо.

Однако, я не понимаю, почему remove() будет потокобезопасным? Например, хэш-ведро имеет ковш-> A-> B-> C-> D-> E и нить A звонки remove(C), механизм, обеспечиваемый реализацией ConcurrentHashMap, состоит в том, чтобы скопировать A, B в следующий связанный список, но в обратном порядке ковш-> B-> A-> DE, а затем сделать A.next к оригиналу D-> E, что приводит к ковш-> B-> A-> DE.

Почему это потокобезопасное? Что, если thread B в настоящее время выполняет итерацию по элементу A, а затем thread A вызывает remove (C). Похоже, он сломается?

+0

О каком «взломе» вы говорите? –

ответ

1

Ну, remove() клонирует элементы HashEntry до удаленного элемента, а не изменяет старые. Таким образом, вы получите

B * -> A * -> D-> Е в ведре, но оригинальный

A-> B-> C-^последовательность не трогали.

Вы можете быть уверены, что A.equals (A *) == false, хотя они будут иметь равные ключи и равные значения. Но это не проблема для итератора, поскольку он просто использует уже собранную запись A, чтобы двигаться дальше.

P.S. ConcurrentHashMap использует блокировки на уровне ковша для модификаций. Это не блокировка.

+0

Идеальный, идеальный смысл. –