2015-12-02 2 views
0

Недавно я посетил интервью, на котором интервьюер задал мне вопрос о HashMap и ConcurrentHashMap. После первоначальных преимуществ по обеспечению безопасности потоков я сказал, что он не бросает ConcurrentModificationException, когда он проходит, а не HashMap.Создает ли ConcurrentHashMap собственную копию?

Интервьюер продолжил и спросил меня, почему он его не бросает. Я сказал, что внутренне HashMap имеет переменную modCount, которая сохраняет количество изменений, внесенных в карту, и Iterator сравнивает это число с тем, которое оно было инициализировано при создании. Если это число отличается, оно выдаст исключение, и это сравнение не произойдет для ConcurrentHashMap.

Он тогда сказал, что ConcurrentHashMap сделает копию себя при обходе.

У меня есть сомнения по поводу этого утверждения, так как они не встречались раньше. Даже чтение документации не дает мне достаточного ответа.

Будет ли он в любой момент копировать (читать или писать)?

+2

* ConcurrentHashMap сделает копию себя при прохождении * - Он ошибается. Посмотрите на исходный код –

+0

'Он тогда сказал, что ConcurrentHashMap сделает копию самого себя при обходе.' Ничего не в javadoc является чистым bs.Другие детали реализации могут быть истинными в определенный момент времени, но не могут претендовать на столь сильное утверждение. – UmNyobe

+1

Надеюсь, вы не получили работу. – UmNyobe

ответ

1

Нет, он не имеет ничего общего с созданием копии чего-либо. И никакое бросание ConcurrentModificationException не обязательно в многопоточной среде.

Несколько вопросов, касающихся ваших вопросов.

  1. ConcurrentModificationException не имеет ничего общего с параллелизмом (и это на самом деле имеет плохое название). Он вызывается, когда вы выполняете итерацию через некоторую структуру данных, и вы снова используете итератор после внесения некоторых изменений в структуру. Это называется поведение fail fast. Из-за такого поведения он может быть брошен в многопоточном контексте, но не имеет никакой зависимости от этого.

  2. ConcurrentHashMap - это сложная структура, и я рекомендую вам прочитать ее. Как это достичь параллельности является

    • Все нити, обращающиеся различные ковши на карте не естественно отделенной поэтому нет необходимости синхронизировать между ними перефразируя исключением случая.

    • Для потоков, обращающихся к одному ковшу, если ведро пустое, он использует CAS i.e. AtomicReference для доступа к единственному элементу в ковше.

    • В случае, если в ведро находится операция hash collision и имеет несколько элементов, ее сохраняют как связанный список (за исключением случая JDK 1.8, который переустанавливает список ссылок в двоичное дерево для достижения лучшей производительности при экстремальном хеш-столкновении). Преимущество связанного списка заключается в том, что он поддерживает параллелизм естественным образом, пока вы работаете с следующим указателем в режиме CAS.

Есть еще много кодирования искусства в ConcurrentHashMap поэтому я предлагаю вам прочитать его исходный код полностью.

Смежные вопросы