HashMap多线程put后get为null和多线程put的时候可能导致元素丢失
一、多线程put后get为null
源码定位
void transfer(Entry[] newTable) {
Entry[] src = table;
int newCapacity = newTable.length;
for ( int j = 0 ; j < src.length; j++) {
Entry e = src[j];
if (e != null ) {
src[j] = null ;//将table[j]设置为null,并发访问到 原table返回的就是null
do {
Entry next = e.next;
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
} while (e != null );
}
}
}
分析:线程1将src[j] = null;即将table[j] = null;因为代码第二行定义了Entry[] src = table;即src和table是对同一对象的引用。
这时切换到线程2,线程2此时若正在调用get(key)方法:
public V get(Object key) { if (key == null) return getForNullKey(); int hash = hash(key.hashCode()); // indexFor方法取得key在table数组中的索引,table数组中的元素是一个链表结构,遍历链表,取得对应key的value for (Entry e = table[indexFor(hash, table.length)]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) return e.value; } return null;
}
若get(key)中key经hash和indexFor()计算后正好落到table[j]上,则此时取到的Entry为null(第11行),直接跳出for循环,来到第21行,return null,违反了错觉。
二、多线程put的时候可能导致元素丢失
源码定位
void addEntry( int hash, K key, V value, int bucketIndex)
{
Entry<K,V> e = table[bucketIndex];
table[bucketIndex] = new Entry<K,V>(hash, key, value, e);//这里线程1和线程2同时获取e,执行后必然有一个丢失
if (size++ >= threshold)
resize( 2 * table.length);
}
问题出在第4行table[bucketIndex] = new Entry<K,V>(hash,key,value,e);如果两个线程同时都取得了e,则他们下一个元素都是e,然后赋值给table元素的时候有一个成功有一个丢失(先赋值的丢失)。
HashMap多线程put后get为null和多线程put的时候可能导致元素丢失的更多相关文章
- Hive concat函数连接后结果为null
Hive concat函数连接后结果为null concat函数是用来连接字符串的 使用示例: select concat('Hello','World','Java'); 运行结果: 最近我们在做需 ...
- 图解集合5:不正确地使用HashMap引发死循环及元素丢失
问题引出 前一篇文章讲解了HashMap的实现原理,讲到了HashMap不是线程安全的.那么HashMap在多线程环境下又会有什么问题呢? 几个月前,公司项目的一个模块在线上运行的时候出现了死循环,死 ...
- 集合(五)不正确地使用HashMap引发死循环及元素丢失
前一篇文章讲解了HashMap的实现原理,讲到了HashMap不是线程安全的.那么HashMap在多线程环境下又会有什么问题呢? 几个月前,公司项目的一个模块在线上运行的时候出现了死循环,死循环的代码 ...
- [转]Java多线程干货系列—(一)Java多线程基础
Java多线程干货系列—(一)Java多线程基础 字数7618 阅读1875 评论21 喜欢86 前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们 ...
- iOS多线程编程指南(一)关于多线程编程(转)
原文:http://www.dreamingwish.com/article/ios-multi-threaded-programming-a-multi-threaded-programming.h ...
- java 中多线程和锁的使用以及获取多线程执行结果
多线程一:原生的写法 关键词 implements 实现 Runnable 类 run() 方法 注意点 : 创建类的实例 InterfaceController inter=new Int ...
- Python 多线程、多进程 (二)之 多线程、同步、通信
Python 多线程.多进程 (一)之 源码执行流程.GIL Python 多线程.多进程 (二)之 多线程.同步.通信 Python 多线程.多进程 (三)之 线程进程对比.多线程 一.python ...
- js null表示没有取到html中的元素 undenfind 表示没有被赋值
js null表示没有取到html中的元素 undenfind 表示没有被赋值
- Response.Redirect("x.aspx);跳转后session为null的解决方法
通常我们做登陆的时候都是登录成功后为管理员保存一些信息,一般都会写类似下面的代码 if(登录成功) { Session["xx"] = "user"; Resp ...
随机推荐
- oracle里实例和数据库之间的关系
一个数据库服务器上可以装几个数据库它们都是用sid来标志,例如orcl1,orcl2,orcl3等等,一个数据库如orcl1中可以有多个实例吗? Oracle数据库,实际上应该是说,我们使用的是Ora ...
- java io系列13之 BufferedOutputStream(缓冲输出流)的认知、源码和示例
本章内容包括3个部分:BufferedOutputStream介绍,BufferedOutputStream源码,以及BufferedOutputStream使用示例. 转载请注明出处:http:// ...
- ruby----%使用法
%{String} 用于创建一个使用双引号括起来的字符串,这个表示法与%Q{String}完全一样 result = %{hello} puts "result is: #{result} ...
- Ubuntu 开启SSH服务以及有关设置:安装,指定端口号、免密登录、远程拷贝
本文所用系统为 Ubuntu 18.04 什么是SSH? 简单说,SSH是一种网络协议,用于计算机之间的加密登录.全名为:安全外壳协议.为Secure Shell的缩写.SSH为建立在应用 ...
- springcloud 服务调用的两种方式
spring-cloud调用服务有两种方式,一种是Ribbon+RestTemplate, 另外一种是Feign.Ribbon是一个基于HTTP和TCP客户端的负载均衡器,其实feign也使用了rib ...
- ACM-ICPC 2018 南京赛区网络预赛 I Skr (马拉车+hash去重)或(回文树)
https://nanti.jisuanke.com/t/30998 题意 给一串由0..9组成的数字字符串,求所有不同回文串的权值和.比如说“1121”这个串中有“1”,“2”,“11”,“121” ...
- wav音频文件格式解析【个人笔记】(自用)
1. WAV格式 wav是微软开发的一种音频文件格式,注意,wav文件格式是无损音频文件格式,相对于其他音频格式文件数据是没有经过压缩的,通常文件也相对比较大些.. 支持多种音频数字,取样频率和声道, ...
- 记录MySQL的一些基础操作
MySQL建表操作 root@localhost 08:05:22> create table stu( -> id int(4) not null, -> name char(20 ...
- ext Ext.grid.去除右边空白
1.当Scroll没有显示时,Ext.grid右边会显示一个空白间隔. 2.解决办法<View> <ext:GridView ForceFit="true" Sc ...
- 【python小练】0005
第 0005 题:你有一个目录,装了很多照片,把它们的尺寸变成都不大于 iPhone5 分辨率的大小. 首先,iphone5的分辨率是1136x640. if条件句判断横(纵)向是否大于对应的ipho ...