2016-11-30 7 views
4

HashMap не должен быть потокобезопасным, тогда почему итераторы бросают concurrentmodificationexception, если кто-то изменил hashMap.HashMap не синхронизирован, то почему исключение параллельной модификации

Также ConcurrentHashMap не выбрасывает это исключение.

ли реализация итератора различна для разных datastructures или есть кто-то метод в рамках этих структур данных, которые проливают ConcurrentModificationException

ответ

3

Когда структура HashMap изменяется (т.е. записи добавляются или удаляются), а HashMap в настоящее время итерации , итератор может потерпеть неудачу во многих отношениях.

Исключением ConcurrentModificationException является исключение из-за того, что любые итераторы не работают в результате таких модификаций.

Вот что modCount поле для:

/** 
* The number of times this HashMap has been structurally modified 
* Structural modifications are those that change the number of mappings in 
* the HashMap or otherwise modify its internal structure (e.g., 
* rehash). This field is used to make iterators on Collection-views of 
* the HashMap fail-fast. (See ConcurrentModificationException). 
*/ 
transient int modCount; 

Это поведение не является специфичным для Map с. Collection s также генерируют это исключение, когда они изменяются во время итерации.

3

Не обманывайте себя мыслью, что Concurrent относится исключительно к многопоточности.

Исключение означает, что сборник был структурно изменен, в то время как вы используете итератор, созданный до изменения. Эта модификация может быть выполнена другой темой, но она может быть той же нитью, что и итерация.

Следующая однопоточный код дает CME:

Map<String, String> map = new HashMap<>(); 
map.put("a", "a"); 
map.put("b", "b"); 

for (String k: map.entrySet()) { 
    map.clear(); 
} 

Или, показывающий итератор в цикле более четко (две петли эквивалентны):

Iterator<String> it = map.entrySet().iterator(); 
while (it.hasNext()) { 
    String k = it.next(); 
    map.clear(); 
} 

it.hasNext() вызывается после map.clear(), в результате чего получается ConcurrentModificationException.

0

ли реализация итератора различна для разных datastructures или есть кто-то метод в рамках этих структур данных, которые проливают ConcurrentModificationException?

Да, существуют различные Iterator реализации внутри Collection классов.

Например, HashMap класс (использует HashIterator внутренне), ConcurrentHashMap (использует KeyIterator, ValueIterator и т.д .. внутри), ArrayList (использует Iterator из AbstractList), и т.д ..

Итератор Hashmap различна из реализации Iterator ConcurrentHashMap.

итератора HashMap в поддерживать номер версии (expectedModCount) и проверки checkForComodification(), как показано ниже:

final void checkForComodification() { 
    if (modCount != expectedModCount) 
     throw new ConcurrentModificationException(); 
} 

Таким образом, в середине итерации, если основной размер коллекции изменяется (путем добавления/удаления элементы), затем Iterator бросок ConcurrentModificationException, как показано выше.

В случае, когда ConcurrentHashMap в Iterator вариантах осуществления не выполняет вышеуказанную проверку, поэтому он не бросает ConcurrentModificationException. Вы также можете найти ту же точку из API ConcurrentHashMaphere.

Они (ConcurrentHashMaps) не бросают ConcurrentModificationException. Однако итераторы предназначены для использования только по одному потоку за раз.

0

Как HashMap является отказоустойчивость быстрой коллекции (Все коллекции под пакетом java.util будут не в состоянии быстро), Итератор Броски исключения, если любая модификация в структуру или ключи главно в случае Hashmap.

У нас есть переменная в Hashmap, которая подсчитывает количество модификаций в Map.and, используя этот итератор, отслеживает отсутствие изменений в коллекции.

transient volatile int modCount; 

Пожалуйста, ознакомьтесь с приведенной ниже ссылке: разница объясняется очень хорошо: Java Modcount (ArrayList) Хороший пример: http://www.journaldev.com/122/java-concurrenthashmap-example-iterator