hashmap之死循环解释

哈希数组

java1.7的hashmap形状如下图
在这里插入图片描述
可以看到有一个table数组,数组中每个元素都是一个链表的头。这个数组的长度与加载因子决定扩容机制,具体算法可以查找网上的内容。每个链表视为一个桶,桶里放的node都是经过hash算法后指向统一位置的元素,这个桶是解决哈希冲突的容器。

头插法

此时如果有一个NodeM,经过hash计算,它应该放到table[0]这个位置,头插法最终的结果是NodeM->Node1->Node2->Node3->NULL

扩容

当一个新元素被put进hashmap后,通过计算,已经超过了阈值,此时需要重新创建一个table,并把之前的元素一个一个的放到新table中,我们假设原来table[0] 这个桶,在新表的位置还是table[0],由于是头插法,需要一个一个的插入,顺序是这样的

  1. Node1->NULL
  2. Node2->Node1->NULL
  3. Node3->Node2->Node1->NULL

  4. 可以发现和之前的顺序是相反的,具体算法如下,实际上就是SWAP函数
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;
            }
        }
    }

简单说明一下怎么个SWAP吧
假设当前桶的情况是这个样子 Node1->Node2->Node3… ,新的table[0] 由于没有数据,此时为NULL

  1. e= Node1 next=Node2,
    e.next = newTable[0]; // 这句话是把Node1的next指向newTable[0],即NULL
    newTable[i] = e;// 把Node1 放到newTable[0]的位置
    最后的结果是Node1->NULL;
  2. 此时e=Node2,next=Node3
    e.next = newTable[0]; // 这句话是把Node2的next指向newTable[0],即Node1
    newTable[i] = e;// 把Node2 放到newTable[0]的位置
    最后的结果是Node2->Node1->NULL;

死循环

简单的说死循环就是链表中出现了一个环

在这里插入图片描述

比如桶是Node1->Node2------->Node3,如果Node1和Node2发生了环,后续对table[0] 进行遍历时就会出现cpu告警

具体解释可以参考死循环的演示,理解《死循环演示》这篇文章的关键是两个线程同时调用hashmap时,都会在自己的私有空间创建一个newTable,第二个线程执行完毕后,也就是把节点逆序后会把它创建的newTable赋值给原table,在resize()函数中有这句话table = newTable。第一个线程在获取原table的各节点顺序时,都会按照这个newTable调整好的逆序来,并没有像它中断前按照的原Table执行。

数据丢失

这种场景很好理解,两个线程同时put一个元素,此时正好发生扩容,且扩容后这个元素假设需要放到table[m]这个位置,初始时这个位置是NULL,线程1判断e.next =table[m]后中断,此时e.next = NULL;线程2执行完毕后,线程1把自己的元素放入了table[m],同时把自己的next指向NULL,实际是替换了线程2的结果,最终导致数据就是。

最后

这篇文章仅仅是一个开头,hashmap还有覆盖等问题,后续接着写。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值