zoukankan      html  css  js  c++  java
  • jdk1.7下HashMap的头插法问题

    jdk1.7,hashmap才用的是头插法,虽然hashmap并不是线程安全的容器,但是在并发情况下,使用hashmap会带来一个问题:

    并发情况下,如果插入元素的两个线程都调用了rehash方法,即扩容方法,会导致链表成环的问题。

    hashmap成环原因的代码出现在transfer代码中,也就是扩容之后的数据迁移部分(如下):

    
    void transfer(Entry[] newTable, boolean rehash) {
    
        int newCapacity = newTable.length;
    
        for (Entry<K,V> e : table) {
    
            while(null != e) {
    
                Entry<K,V> next = e.next;
    
                if (rehash) {
    
                    e.hash = null == e.key ? 0 : hash(e.key);
    
                }
    
                int i = indexFor(e.hash, newCapacity);
    
                e.next = newTable[i];
    
                newTable[i] = e;
    
                e = next;
    
            }
    
        }
    
    }
    
    
    
    

    解释一下transfer的过程:

    首先获取新表的长度,之后遍历新表的每一个entry,然后每个ertry中的链表,以反转的形式,形成rehash之后的链表。

    并发问题:

    若当前线程此时获得ertry节点,但是被线程中断无法继续执行,此时线程二进入transfer函数,并把函数顺利执行,此时新表中的某个位置有了节点,之后线程一获得执行权继续执行,因为并发transfer,所以两者都是扩容的同一个链表,当线程一执行到e.next = new table[i] 的时候,由于线程二之前数据迁移的原因导致此时new table[i] 上就有ertry存在,所以线程一执行的时候,会将next节点,设置为自己,导致自己互相使用next引用对方,因此产生链表,导致死循环。

    作者:lenny611
    链接:https://www.jianshu.com/p/9da90b333f35
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 相关阅读:
    使用mybatis如果类属性名和数据库中的属性名不一样取值就会为null
    学习mybatis时出现了java.io.IOException: Could not find resource EmployeeMapper.xml
    配置mybatis-config.xml出现过很诡异的现象
    mybatis学习(一)
    报错cannot be cast to javassist.util.proxy.Proxy
    列车调度
    三角形
    土豪聪要请客(stol)
    Jams倒酒(pour)
    Data
  • 原文地址:https://www.cnblogs.com/nineberg/p/12507218.html
Copyright © 2011-2022 走看看