1. resize死循环
我们都知道HashMap初始容量大小为16,一般来说,当有数据要插入时,都会检查容量有没有超过设定的thredhold,如果超过,需要增大Hash表的尺寸,但是这样一来,整个Hash表里的元素都需要被重算一遍。这叫rehash,这个成本相当的大。
大概看下transfer:
-
对索引数组中的元素遍历
-
对链表上的每一个节点遍历:用 next 取得要转移那个元素的下一个,将 e 转移到新 Hash 表的头部,使用头插法插入节点。
-
循环2,直到链表节点全部转移
-
循环1,直到所有索引数组全部转移
经过这几步,我们会发现转移的时候是逆序的。假如转移前链表顺序是1->2->3,那么转移后就会变成3->2->1。这时候就有点头绪了,死锁问题不就是因为1->2的同时2->1造成的吗?所以,HashMap 的死锁问题就出在这个transfer()函数上。
1.1 单线程 rehash 详细演示
单线程情况下,rehash 不会出现任何问题:
-
假设hash算法就是最简单的 key mod table.length(也就是数组的长度)。
-
最上面的是old hash 表,其中的Hash表的 size = 2, 所以 key = 3, 7, 5&