HashMap底层详解-003-resize并发下的安全问题

Posted JavaWeb架构师

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HashMap底层详解-003-resize并发下的安全问题相关的知识,希望对你有一定的参考价值。

HashMap底层详解-003-resize、并发下的安全问题

HashMap底层详解-003-resize、并发下的安全问题

HashMap底层详解-003-resize、并发下的安全问题

HashMap底层详解-003-resize、并发下的安全问题

HashMap扩容的时机是:  当前HashMap中存放的元素个数 > HashMap的当前总长度 * loadFactor(loadFactor默认值是0.75) 时进行扩容,扩容之后的长度是当前长度的2倍(比如现在存放了 16 * 0.75 = 12个,再存放第十三个元素的时候,HashMap就会自动的扩容,扩展成 2 * 16 = 32个 )。

HashMap底层详解-003-resize、并发下的安全问题


当扩容之后,需要重新计算元素的位置,这是一个非常耗时的操作,所以我们最好能预设长度,比如我们有1000个元素,那么 new HashMap(1000)? 不!前面我们说过了,应该设置成2的幂,所以 new HashMap(1024)? 其实我们设置成1000也会被调整成1024的,但是这样就可以了吗?不!当元素超过 1024*0.75 = 768个的时候会进行自动扩容,所以我们应该是new HashMap(2048)。


HashMap底层详解-003-resize、并发下的安全问题

HashMap底层详解-003-resize、并发下的安全问题

  1. 新建Entry,长度是原长度的两倍


    2.rehash,遍历原有的数组,把那些元素重新映射到新的数组上(参考咱们前面的公式,length变了,结果自然就变了)。


HashMap底层详解-003-resize、并发下的安全问题

HashMap底层详解-003-resize、并发下的安全问题

HashMap底层详解-003-resize、并发下的安全问题


  1. 现在有一个HashMap如下,如果再插入一个元素就会进行扩容


HashMap底层详解-003-resize、并发下的安全问题


2.现在有线程A、B同时执行对这个HashMap的元素插入操作


HashMap底层详解-003-resize、并发下的安全问题


3.完成插入之后,A、B线程都要对这个HashMap进行扩容


HashMap底层详解-003-resize、并发下的安全问题


4.首先线程A执行


HashMap底层详解-003-resize、并发下的安全问题


当线程A对原HashMap遍历到了php位置的时候,刚刚执行完上面红框部分的代码,这时候:
e = PHP
next = Java
PHP.next = Java
Java.next = null


5.这时候线程A被挂起,线程B完成了所有的操作

HashMap底层详解-003-resize、并发下的安全问题


Java.next = PHP
PHP.next = null


6.线程A恢复执行-下标值

HashMap底层详解-003-resize、并发下的安全问题


i的值和线程B中PHP链表的下标一样(参数都是一样,结果就是一样的)


7.线程A恢复执行-PHP第一次
当前状态:
e = PHP
next = Java
Java.next = PHP
PHP.next = null


HashMap底层详解-003-resize、并发下的安全问题

这时候PHP被放到了线程A的新HashMap中


HashMap底层详解-003-resize、并发下的安全问题

现在:
e = Java
next = Java
Java.next = PHP
PHP.next = null


8.线程A恢复执行-Java第一次


HashMap底层详解-003-resize、并发下的安全问题


当前状态:
e = Java
next = PHP
Java.next = PHP
PHP.next = null


代码再次执行到了:


HashMap底层详解-003-resize、并发下的安全问题

这时候Java被放到了线程A的HashMap的i位置的表头

HashMap底层详解-003-resize、并发下的安全问题

现在:
e = PHP
next = PHP
Java.next = PHP
PHP.next = null


9.线程A恢复执行-PHP第二次(出现问题)


HashMap底层详解-003-resize、并发下的安全问题


当前状态:
e = PHP
next = null

HashMap底层详解-003-resize、并发下的安全问题


当前状态:
PHP.next = Java
Java.next = PHP
e = null


HashMap底层详解-003-resize、并发下的安全问题


HashMap底层详解-003-resize、并发下的安全问题

HashMap底层详解-003-resize、并发下的安全问题

HashMap底层详解-003-resize、并发下的安全问题

HashMap底层详解-003-resize、并发下的安全问题









2.简书:http://www.jianshu.com/u/53b3f4658edc
3.CSDN:http://blog.csdn.net/qq_33605778?viewmode=contents


视频教程














JavaWeb架构师







点击阅读原文,支持作者!


以上是关于HashMap底层详解-003-resize并发下的安全问题的主要内容,如果未能解决你的问题,请参考以下文章

高并发下的HashMap

并发下诡异的HashMap

2.8.3 并发下诡异的HashMap

高并发下,HashMap会产生哪些问题?

漫画:高并发下的HashMap

HashMap并发下死循环问题解析