写个例子说明HashMap线程不安全

投稿- 2023-08-24 08:14:20

Java8系列之重新认识HashMap

大家好,感谢邀请,今天来为大家分享一下写个例子说明HashMap线程不安全的问题,以及和hashmap为什么是线程不安全的的一些困惑,大家要是还不太明白的话,也没有关系,因为接下来将为大家分享,希望可以帮助到大家,解决大家的问题,下面就开始吧!

本文目录

  1. 如何让HashMap变成线程安全的
  2. HashMap线程安全的吗
  3. 写个例子说明HashMap线程不安全
  4. hashmap有哪些线程安全的方式

如何让HashMap变成线程安全的

有2种办法让HashMap线程安全,分别如下:

方法一:通过Collections.synchronizedMap()返回一个新的Map,这个新的map就是线程安全的。这个要求大家习惯基于接口编程,因为返回的并不是HashMap,而是一个Map的实现。

方法二:重新改写了HashMap,具体的可以查看java.util.concurrent.ConcurrentHashMap.这个方法比方法一有了很大的改进。

HashMap线程安全的吗

hashMap是否线程安全基本上是在每次面试都会问的了,而99%的JAVA程序员都知道hashMap是非线程安全的,不过知道其底层原因的应该不多,下面来说下为什么是线程不安全的!

我们都知道,hashMap是一种在开发中最常用的数据结构(key-value型),因为它很快(O(1)常数级别的查询),在存储的时候通过计算key的hash值,将value存在对应的桶里(数组的一个元素),然后通过头插法插入桶中的单向链表里,如下图所示:

这个过程是线程安全的,因为就算是发生了线程同享资源,无非就是插入的数据顺序问题而已,无伤大雅,但是我们都知道,hashMap为了防止数据查询过慢(如果单链表中的数据过大,相当于O(1)常数级别的性能下降为O(N)线性级别),采取了自动扩容的方式,一旦存储数据的大小size超过了总容量的0.75(装载因子),就发生自动扩容,安全问题也就随之诞生了!

hashMap怎么实现扩容呢?一旦需要扩容的时候,会新建一个两倍容量的hashMap,并把原来的元素重新做hash存入新的hash数组,底层源码使用的resize方法:

在resize方法中需要调用transfer方法,方法很简单,无非就是遍历老hash数组,然后重新放入新的hash数组中,如下:

当thread1执行到Entry<k,v>next=e.next的时候,把原来的key7指向key3,变为了key3指向key7,因为java是抢占式线程,此时thread2开始执行,不过在线程2中的快照中,还是key7指向key3(但实质key3已经指向了key7)!

经过线程2的处理完成,线程继续处理,这个时候key3指向key7,反过来key7也指向key3,这时候单链表变成了环形链表:

等到查询方法查找到这个hash数组的时候,查询出现了死循环,永远卡死在这,CPU跑满。

所以hashMap是非线程安全的,相对应的hashTable拥有着和hashMap类似的结构,但是因为hashTable中的所有方法都加了锁(synchonize),所以在多线程处理中,应该是用hashTable来换取数据的安全性!

hashMap就说到这,各位朋友,有钱的捧个钱场,没钱的点个赞,更多的技术分享,敬请关注。。。

写个例子说明HashMap线程不安全

谢谢邀请!下面介绍一下jdk1.7的扩容死循环问题!

HashMap扩容的源代码如下:

resize扩容方法中最重要的代码如下:

resize扩容步骤如下:

根据newCapacity生成一个数组。

遍历旧的数组,然后对其中的每一个值进行hash,重新进行插入。

修改扩容的阀值:threshold。

下面我们分别展示在单线程和多线程的环境的扩容

我们定义的Map为Map<Integer,String>

单线程环境下的扩容

我们先定义有个简单的hash,hash=key%length

默认hash表的长度为2,插入的元素为5911

5%2=1;

9%2=1;

11%2=1;

三个元素都碰撞在下标为1的位置上。

下面我们扩容到4:

5%4=1;

9%4=1;

11%4=3;

扩容步骤如下:

并发环境下的扩容

首先线程1和线程2同时扩容

线程1和线程2的e为5。e.next=9

但是此时,线程1由于调度问题暂停执行。

线程2继续执行,执行结束后如下:

这时,线程1被唤醒了。这时线程1的e为5,e.next=9;

此时:

处理完5后,我们就要处理9。

此时

因为在线程2中9的下一个节点为5,所以还要继续处理5,会把5放到线程1的table[1]处,

这时就会循环生成一个循环列表。11这个元素时无法加入到线程1里面了。

hashmap有哪些线程安全的方式

第一种是使用JUC并发工具包里面的ConcurrentHashMap,这是一个线程安全的HashMap类,第二种是利用Collections工具类的静态方法Collections.synchronizedMap来构造线程安全的HashMap。

好了,文章到这里就结束啦,如果本次分享的写个例子说明HashMap线程不安全和hashmap为什么是线程不安全的问题对您有所帮助,还望关注下本站哦!

面试官问你HashMap为什么线程不安全,体现在哪 举个例子看看
  • 声明:本文内容来自互联网不代表本站观点,转载请注明出处:bk.0755org.com/14/139747.html
上一篇:军转民警什么意思(军转警工资多少)
下一篇:内衣裤清洗剂洗完为什么会臭臭的(内衣裤清洗剂哪个牌子的好)
相关文章
返回顶部小火箭