美文网首页
关于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

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