zoukankan      html  css  js  c++  java
  • HashMap多线程put后get为null和多线程put的时候可能导致元素丢失

    一、多线程put后get为null 

      源码定位

     1 void  transfer(Entry[] newTable) {
     2      Entry[] src = table;
     3      int  newCapacity = newTable.length;
     4      for  ( int  j =  0 ; j < src.length; j++) {
     5          Entry e = src[j];
     6          if  (e !=  null ) {
     7              src[j] =  null ;//将table[j]设置为null,并发访问到 原table返回的就是null
     8              do  {
     9                  Entry next = e.next;
    10                  int  i = indexFor(e.hash, newCapacity);
    11                  e.next = newTable[i];
    12                  newTable[i] = e;
    13                  e = next;
    14              }  while  (e !=  null );
    15          }
    16      }
    17 }

      分析:线程1将src[j] = null;即将table[j] = null;因为代码第二行定义了Entry[] src = table;即src和table是对同一对象的引用。

      这时切换到线程2,线程2此时若正在调用get(key)方法:

     1 public V get(Object key) {  
     2 
     3         if (key == null)  
     4 
     5             return getForNullKey();  
     6 
     7         int hash = hash(key.hashCode());  
     8 
     9         // indexFor方法取得key在table数组中的索引,table数组中的元素是一个链表结构,遍历链表,取得对应key的value  
    10 
    11         for (Entry e = table[indexFor(hash, table.length)]; e != null; e = e.next) {  
    12 
    13             Object k;  
    14 
    15             if (e.hash == hash && ((k = e.key) == key || key.equals(k)))  
    16 
    17                 return e.value;  
    18 
    19         }  
    20 
    21         return null; 
    22 }

      若get(key)中key经hash和indexFor()计算后正好落到table[j]上,则此时取到的Entry为null(第11行),直接跳出for循环,来到第21行,return null,违反了错觉。

    二、多线程put的时候可能导致元素丢失

      源码定位

    1 void  addEntry( int  hash, K key, V value,  int  bucketIndex)
    2 {
    3      Entry<K,V> e = table[bucketIndex];
    4      table[bucketIndex] =  new  Entry<K,V>(hash, key, value, e);//这里线程1和线程2同时获取e,执行后必然有一个丢失
    5      if  (size++ >= threshold)
    6          resize( 2  * table.length);
    7 }

      问题出在第4行table[bucketIndex] = new Entry<K,V>(hash,key,value,e);如果两个线程同时都取得了e,则他们下一个元素都是e,然后赋值给table元素的时候有一个成功有一个丢失(先赋值的丢失)。

  • 相关阅读:
    php的webservice的soapheader认证问题
    训练与解码
    ajax 图片上传
    js倒计时
    数据分析有价值的博客
    [Luogu P5675][GZOI2017]取石子游戏
    [BZOJ4558/LOJ2025/Luogu3271][GZOI2016/JLOI2016/SHOI2016]方
    [BZOJ4557/LOJ2024/Luogu3267][GZOI2016/JLOI2016/SHOI2016]侦察守卫
    PKUWC2019游记
    随机带权选取文件中一行 分类: linux c/c++ 2014-06-02 00:11 344人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/codingmengmeng/p/9948749.html
Copyright © 2011-2022 走看看