说明方法有几种(运用的说明方法有几种)
9712023-11-26
大家好,感谢邀请,今天来为大家分享一下写个例子说明HashMap线程不安全的问题,以及和hashmap为什么是线程不安全的的一些困惑,大家要是还不太明白的话,也没有关系,因为接下来将为大家分享,希望可以帮助到大家,解决大家的问题,下面就开始吧!
本文目录
有2种办法让HashMap线程安全,分别如下:
方法一:通过Collections.synchronizedMap()返回一个新的Map,这个新的map就是线程安全的。这个要求大家习惯基于接口编程,因为返回的并不是HashMap,而是一个Map的实现。
方法二:重新改写了HashMap,具体的可以查看java.util.concurrent.ConcurrentHashMap.这个方法比方法一有了很大的改进。
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就说到这,各位朋友,有钱的捧个钱场,没钱的点个赞,更多的技术分享,敬请关注。。。
谢谢邀请!下面介绍一下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里面了。
第一种是使用JUC并发工具包里面的ConcurrentHashMap,这是一个线程安全的HashMap类,第二种是利用Collections工具类的静态方法Collections.synchronizedMap来构造线程安全的HashMap。
好了,文章到这里就结束啦,如果本次分享的写个例子说明HashMap线程不安全和hashmap为什么是线程不安全的问题对您有所帮助,还望关注下本站哦!