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 ...
随机推荐
- python 模块一(random,counter,defaultdict,time,wraps,reduce) 栈 队列 双向队列
####################总结####################### 模块:你写的py文件 引用其他模块 1.import 模块 2.from 模块 import 功能,类,变量 ...
- angular学习—组件
组件: vue组件:xxx.vue react组件:xxx.js+xxx.css angular组件:xxx.ts+xxx.css+xxx.html angular的装饰器: @ngModule:an ...
- sc (service control )
SC 是用来与服务控制管理器和服务进行通信 net: net start 服务名 net stop 服务名 sc: sc config 服务名 start= demand //手动 sc con ...
- [leetcode-117]填充每个节点的下一个右侧节点指针 II
(1 AC) 填充每个节点的下一个右侧节点指针 I是完美二叉树.这个是任意二叉树 给定一个二叉树 struct Node { int val; Node *left; Node *right; Nod ...
- HDU 1045(炮台安置 DFS)
题意是在 n*n 的方格中进行炮台的安置,炮台不能处于同一行或同一列(类似于八皇后问题),但若是炮台间有墙壁阻挡,则可以同时安置这对炮台.问图中可以安放的最大炮台数目. 用深搜的方法,若此处为空地,则 ...
- Shell编程(七)函数
1. 函数开始 #!/bin/bash foo() { echo "Function foo is called"; } echo "-=start=-" fo ...
- 复杂sql查询语句
视图也叫虚表 1.表中保存实际数据,视图保存从表中取出数据所使用的SELECT语句,视图也是一张表,之间区别是是否保存实际数据. 2.使用视图可以完成跨多表查询数据.可以将常用SELECT语句做成视图 ...
- nginx接入let's encrypt
按以下步骤: 一.放开443端口 我的是云服务器,默认没开放443端口,需要先在控制台放开 二.使用let’s encrypt 生成证书 执行以下命令: git clone https://githu ...
- 开源框架.netCore DncZeus学习(五)下拉树的实现
千里之行,始于足下,先从一个小功能研究起,在菜单管理页面有一个下拉树,先研究下它怎么实现的 1.先找到menu.vue页面 惯性思维先搜索请选择三个字,原来是动态生成的 再向上找DropDown组件, ...
- None.js 第六步 Stream(流)
输出流 var fs = require("fs"); var data = ''; // 创建可读流 var readerStream = fs.createReadStream ...