你可知HashMap为什么是线程不安全的_第1页
你可知HashMap为什么是线程不安全的_第2页
你可知HashMap为什么是线程不安全的_第3页
你可知HashMap为什么是线程不安全的_第4页
你可知HashMap为什么是线程不安全的_第5页
全文预览已结束

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第你可知HashMap为什么是线程不安全的目录HashMap的线程不安全HashMap中的put()方法数据的覆盖一数据的覆盖二

HashMap的线程不安全

HashMap的线程不安全主要体现在下面两个方面

在jdk1.7中,当并发执行扩容操作时会造成环形链和数据丢失的情况在jdk1.8中,在并发执行put操作时会发生数据覆盖的情况

对于jdk1.7中HashMap的线程不安全,暂且不谈了,我们主要看看jdk1.8中的

HashMap中的put()方法

该put()方法是jdk1.8中的

publicVput(Kkey,Vvalue){

returnputVal(hash(key),key,value,false,true);

finalVputVal(inthash,Kkey,Vvalue,booleanonlyIfAbsent,

booleanevict){

NodeK,V[]tab;NodeK,Vintn,i;

//判断table[]是否为空,如果是空的就创建一个table[],并获取他的长度n

if((tab=table)==null||(n=tab.length)==0)

n=(tab=resize()).length;

//如果单链表节点NodeK,Vp==tab[i=(n-1)hash])==null,

//就直接put进单链表中,说明此时并没有发生Hash冲突

if((p=tab[i=(n-1)hash])==null)

tab[i]=newNode(hash,key,value,null);

else{

//说明索引位置已经放入过数据了,已经在单链表处产生了Hash冲突

NodeK,VKk;

//判断put的数据和之前的数据是否重复

if(p.hash==hash

//进行key的hash值和key的equals()和==比较,如果都相等,则初始化数组NodeK,Ve

((k=p.key)==key||(key!=nullkey.equals(k))))

e=p;

//判断是否是红黑树,如果是红黑树就直接插入树中

elseif(pinstanceofTreeNode)

e=((TreeNodeK,V)p).putTreeVal(this,tab,hash,key,value);

else{

//如果不是红黑树,就遍历每个节点,判断单链表长度是否大于等于7,

//如果单链表长度大于等于7,数组的长度小于64时,会优先选择扩容

//如果单链表长度大于等于7,数组的长度大于64时,才会选择单链表---红黑树

for(intbinCount=0;;++binCount){

if((e=p.next)==null){

//采用尾插法,在单链表中插入数据

p.next=newNode(hash,key,value,null);

//如果binCount=8-1

if(binCount=TREEIFY_THRESHOLD-1)

treeifyBin(tab,hash);

break;

//判断索引每个元素的key是否可要插入的key相同,如果相同就直接覆盖

if(e.hash==hash

((k=e.key)==key||(key!=nullkey.equals(k))))

break;

p=e;

//说明数组或者单链表中有相同的key,因此只需要将value覆盖,并将oldValue返回即可

if(e!=null){

VoldValue=e.value;

if(!onlyIfAbsent||oldValue==null)

e.value=value;

afterNodeAccess(e);

returnoldValue;

//说明没有key相同,因此要插入一个key-value,并记录内部结构变化次数

++modCount;

//判断是否扩容

if(++sizethreshold)

resize();

afterNodeInsertion(evict);

returnnull;

数据的覆盖一

第13行代码是判断是否出现hash冲突的,假设两个线程A、B都在进行put操作,并且它们put数据的key的hash值是相同的,同时它们keyA==keyB为true或者keyA.equals(keyB)为true,也就是说它们put数据的value是不相同的

当线程A执行完第13行代码后由于时间片耗尽导致被挂起,而线程B得到时间片后在该单链表处插入了元素,完成了正常的插入

然后线程A获得时间片,由于之前已经进行了hash冲突的判断,所有此时不会再进行判断,而是直接进行插入覆盖,这就导致了线程B插入的数据被线程A覆盖了,从而发生了线程不安全

数据的覆盖二

第58行处有个++size,我们这样想,还是线程A、B,这两个线程同时进行put操作时,假设当前HashMap的size大小为10

当线程A执行到第58行代码时,从主内存中获得size的值为10后准备进行+1操作,但是由于时间片耗尽只好让出CPU

于是线程B得到CPU调度,还是从主内存中拿到size的值10进行+1操作,完成了put操作,并将size=11写回了主内存

然后线程A再次得到CPU调度,并继续执行(此时size的值仍为10),当执行完put操作后,还是将size=11写了

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论