HashMap多线程下的问题
程序员文章站
2022-05-02 18:07:24
...
Java的文档说HashMap是非线程安全的,应该用ConcurrentHashMap。那么HashMap在多线程环境下会出现什么问题呢?
- 多线程put,get时出现死循环,导致CPU利用率过高
- 多线程put,可能导致元素丢失
- put非null元素后get出来的却是null
以上情况是怎么产生的?
1.多线程put,get时出现死循环,导致CPU利用率过高
1.CPU利用率过高一般是因为出现了出现了死循环,导致部分线程一直运行,占用cpu时间。问题原因就是HashMap是非线程安全的,多个线程put的时候造成了某个key值Entry key List的死循环。大量线程被hang住可能导致服务器宕机。
循环链表出现的原理分析:
(网上很多例子,这里就不举例了)
参考:http://www.voidcn.com/article/p-hcuguoxo-bob.html
循环的产生是因为新链表的顺序跟旧的链表是完全相反的,所以只要保证建新链时还是按照原来的顺序的话就不会产生循环。
JDK8是用 head 和 tail 来保证链表的顺序和之前一样,这样就不会产生循环引用。
JDK8如何进行扩容参考《HashMap底层原理》
2:多线程put,可能导致元素丢失
主要问题出在addEntry方法的new Entry<K,V>(hash, key, value, e),如果两个线程都同时取得了e,则他们下一个元素都是e,然后赋值给table元素的时候有一个成功有一个丢失。
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);
//查看当前的size是否超过了我们设定的阈值threshold,如果超过,需要resize
if (size++ >= threshold)
resize(2 * table.length);
}
3:put非null元素后get出来的却是null
在transfer方法中代码如下:
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;
do {
Entry next = e.next;
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
} while (e != null);
}
}
}
在这个方法里,将旧数组赋值给src,遍历src,当src的元素非null时,就将src中的该元素置null,即将旧数组中的元素置null了:
if (e != null) {
src[j] = null;
上一篇: python3网络爬虫学习4.3pyquery的使用学习
下一篇: python中的zip方法详解
推荐阅读
-
LNMP环境下,解决项目缓冲慢、502以及配置https的问题
-
windows下配置apache+php+mysql时出现问题的处理方法
-
linux下tar命令遇到error:"Error exit delayed from previous errors"的问题及解决
-
IE8下载不提示保存对话框问题的解决方法
-
表单button的outline在firefox浏览器下的问题
-
vs2012编译的程序不能在XP和2003下执行问题的解决方法
-
解决跨帧菜单在IE7下面无法正确定位菜单的问题
-
Broadcom网卡linux系统下无法连接到网络问题的解决办法
-
解决Windows环境下安装 mysql-8.0.11-winx64 遇到的问题
-
Microsoft Visual Studio 2010 Ultimate 下安装wcsf 2010出现问题的解决方法