加入收藏 | 设为首页 | 会员中心 | 我要投稿 开发网_开封站长网 (http://www.0378zz.com/)- 科技、AI行业应用、媒体智能、低代码、办公协同!
当前位置: 首页 > 服务器 > 安全 > 正文

HashMap 为何线程不安全

发布时间:2022-07-18 08:38:49 所属栏目:安全 来源:互联网
导读:前言:我们都知道HashMap是线程不安全的,在多线程环境中不建议使用,但是其线程不安全主要体现在什么地方呢,本文将对该问题进行解密。 在jdk1.8中对HashMap做了很多优化,这里先分析在jdk1.7中的问题,相信大家都知道在jdk1.7多线程环境下HashMap容易出现
  前言:我们都知道HashMap是线程不安全的,在多线程环境中不建议使用,但是其线程不安全主要体现在什么地方呢,本文将对该问题进行解密。
 
  在jdk1.8中对HashMap做了很多优化,这里先分析在jdk1.7中的问题,相信大家都知道在jdk1.7多线程环境下HashMap容易出现死循环,这里我们先用代码来模拟出现死循环的情况:
 
  复制
  public class HashMapTest {
  
       public static void main(String[] args) {
           HashMapThread thread0 = new HashMapThread();
           HashMapThread thread1 = new HashMapThread();
           HashMapThread thread2 = new HashMapThread();
           HashMapThread thread3 = new HashMapThread();
           HashMapThread thread4 = new HashMapThread();
           thread0.start();
           thread1.start();
           thread2.start();
           thread3.start();
           thread4.start();
       } 
 
  从堆栈信息中可以看到出现死循环的位置,通过该信息可明确知道死循环发生在HashMap的扩容函数中,根源在transfer函数中,jdk1.7中HashMap的transfer函数如下:
 
  在对table进行扩容到newTable后,需要将原来数据转移到newTable中,注意10-12行代码,这里可以看出在转移元素的过程中,使用的是头插法,也就是链表的顺序会翻转,这里也是形成死循环的关键点。下面进行详细分析。
 
  前提条件:
 
  这里假设
 
  #1.hash算法为简单的用key mod链表的大小。
 
  #2.最开始hash表size=2,key=3,7,5,则都在table[1]中。
 
  #3.然后进行resize,使size变成4。
 
  这里的转移过程,不再进行详述,只要理解transfer函数在做什么,其转移过程以及如何对链表进行反转应该不难。
 
  然后在多线程环境下,假设有两个线程A和B都在进行put操作。线程A在执行到transfer函数中第11行代码处挂起,因为该函数在这里分析的地位非常重要,因此再次贴出来。

(编辑:开发网_开封站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读