繁体   English   中英

HashMap不同步然后为什么是parallelmodification异常

[英]HashMap is not synchronized then why concurrentmodification exception

HashMap不应该是线程安全的,那么如果有人修改了hashMap,为什么迭代器会抛出concurrentmodificationexception

ConcurrentHashMap也不会抛出此异常。

Iterator实现对于不同的数据结构是不同的,或者这些数据结构中有某些方法抛出ConcurrentModificationException

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也会抛出此异常。

不要误以为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()之后map.clear() ,导致ConcurrentModificationException

Iterator实现对于不同的数据结构是不同的,或者这些数据结构中有某些方法抛出ConcurrentModificationException?

是的, Collection类中有不同的Iterator实现

例如, HashMap类( HashIterator内部使用HashIterator ), ConcurrentHashMap (在内部使用KeyIteratorValueIterator等)ArrayList (使用来自AbstractList Iterator )等。

HashMap的Iterator与ConcurrentHashMap的Iterator实现不同。

HashMap的Iterator维护版本号( expectedModCount )并验证checkForComodification() ,如下所示:

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

因此,在迭代过程中,如果修改了底层集合大小(通过添加/删除元素),则Iterator抛出ConcurrentModificationException如上所示。

ConcurrentHashMapIterator实现不执行上述检查,因此它不会抛出ConcurrentModificationException 你也可以在这里找到来自API ConcurrentHashMap的相同点。

它们(ConcurrentHashMaps)不会抛出ConcurrentModificationException。 但是,迭代器设计为一次只能由一个线程使用。

由于HashMap是一个快速失败的集合(java.util包下的所有集合都快速失败),如果对Hashmap主要进行结构或键的任何修改,则Iterator抛出异常。

我们在Hashmap中有一个变量来计算Map中的修改数量。使用该迭代器可以跟踪对Collection进行的修改。

transient volatile int modCount;

请阅读以下链接:差异很好解释: Java Modcount(ArrayList)好示例: http//www.journaldev.com/122/java-concurrenthashmap-example-iterator

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM