美文网首页
关于HashMap的Concurrentmodification

关于HashMap的Concurrentmodification

作者: JeniusYang | 来源:发表于2017-06-14 10:01 被阅读0次

错误堆栈如下

java.util.ConcurrentModificationException
        at java.util.HashMap$HashIterator.nextEntry(HashMap.java:922)
        at java.util.HashMap$KeyIterator.next(HashMap.java:956)
        ...

hashMap的相关实现源码如下:

final Entry<K,V> nextEntry() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            Entry<K,V> e = next;
            if (e == null)
                throw new NoSuchElementException();

            if ((next = e.next) == null) {
                Entry[] t = table;
                while (index < t.length && (next = t[index++]) == null)
                    ;
            }
            current = e;
            return e;
        }

        public void remove() {
            if (current == null)
                throw new IllegalStateException();
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            Object k = current.key;
            current = null;
            HashMap.this.removeEntryForKey(k);
            expectedModCount = modCount;
        }

显然,工程中使用了迭代器遍历hashMap时并且map的size被修改过了,导致modCount != expectedModCount,原因是hash迭代器在将modCount赋值给expectedModCount后,modCount的值被其它线程修改掉了。

  private abstract class HashIterator<E> implements Iterator<E> {
        Entry<K,V> next;        // next entry to return
        int expectedModCount;   // For fast-fail
        int index;              // current slot
        Entry<K,V> current;     // current entry

        HashIterator() {
            expectedModCount = modCount;
            if (size > 0) { // advance to first entry
                Entry[] t = table;
                while (index < t.length && (next = t[index++]) == null)
                    ;
            }
        }

解决方法:使用ImmutableMap进行线程安全的复制。

 hashMap = ...
 copyUserMap = ImmutableMap.copyOf(hashMap);
 Iterator<String> keys = copyUserMap.keySet().iterator();
 while (keys.hasNext()) {
               ...
 }

由于HashMap是线程不安全的,这样在遍历的时候不会因为多线程的修改map而导致并发异常。除了该方法,还可以使用concurrentHashMap,获取线程锁解决。

相关文章

  • 关于HashMap的Concurrentmodification

    错误堆栈如下 hashMap的相关实现源码如下: 显然,工程中使用了迭代器遍历hashMap时并且map的size...

  • HashMap源码分析

    hashmap的分析网上优秀的文章有很多,个人比较推荐美团技术博客上关于hashmap的介绍。由于hashmap广...

  • 源码修炼笔记之HashMap源码解析

    HashMap高频面试题 HashMap备受面试官的青睐,笔者几乎每次面试都会遇到关于HashMap的问题,整理出...

  • ConcurrentHashMap源码分析(JDK8)

    导入 ConcurrentHashMap是HashMap的线程安全版本的实现版本,关于HashMap的分析总结,可...

  • jdk1.8 HashMap红黑树源码解析

    这篇博客主要讲解HashMap1.8的新增特性:红黑树,关于HashMap的其他内容推荐博客HashMap真的教科...

  • HashMap解读

    相信大家对HashMap都非常熟悉, 网上也有很多关于hashmap的源码解析, 此文仅记录本人对HashMap的...

  • 关于HashMap

    1、为什么用HashMap? HashMap是一个散列桶(数组和链表),它储存的内容是键值对映射(key-valu...

  • 关于HashMap

    先了解下相关概念: 哈希(Hash):一般叫做散列,意思就是把一堆任意长度的字符串、数字或者二进制输入通过一定的算...

  • Java·Hashtable、HashMap、Concurren

    关于HashMap详请见Java·hashmap本文主要讲讲三者的区别 ConcurrentHashMap锁 JD...

  • [Java]重学Java-Map

    HashMap 关于HashMap的源码解析,笔者已经写过,这里不在重复介绍. HashSet-集合 如果你需要判...

网友评论

      本文标题:关于HashMap的Concurrentmodification

      本文链接:https://www.haomeiwen.com/subject/fkksqxtx.html