Hashmap在并发环境下,可能出现的问题:

1、多线程put时可能会导致get无限循环,具体表现为CPU使用率100%;

原因:在向HashMap put元素时,会检查HashMap的容量是否足够,如果不足,则会新建一个比原来容量大两倍的Hash表,然后把数组从老的Hash表中迁移到新的Hash表中,迁移的过程就是一个rehash()的过程,多个线程同时操作就有可能会形成循环链表,所以在使用get()时,就会出现Infinite Loop的情况

// tranfer()片段
// 这是在resize()中调用的方法,resize()就是HashMap扩容的方法
for (int j = 0; j < src.length; j++) {
Entry e = src[j];
if (e != null) {
src[j] = null;
do {
Entry next = e.next; //假设线程1停留在这里就挂起了,线程2登场
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
} while (e != null);
}
}

线程一:Thread1影响key1



线程二:Thread1影响key2



因为两条线程的影响,倒是出现循环的情况



出现问题的测试代码:

import java.util.HashMap;
import java.util.concurrent.atomic.AtomicInteger; public class MyThread extends Thread {
/**
* 类的静态变量是各个实例共享的,因此并发的执行此线程一直在操作这两个变量
* 选择AtomicInteger避免可能的int++并发问题
*/
private static AtomicInteger ai = new AtomicInteger(0);
//初始化一个table长度为1的哈希表
private static HashMap<Integer, Integer> map = new HashMap<Integer, Integer>(1);
//如果使用ConcurrentHashMap,不会出现类似的问题
// private static ConcurrentHashMap<Integer, Integer> map = new ConcurrentHashMap<Integer, Integer>(1); public void run() {
while (ai.get() < 100000) { //不断自增
map.put(ai.get(), ai.get());
ai.incrementAndGet();
} System.out.println(Thread.currentThread().getName() + "线程即将结束");
} public static void main(String[] args) {
MyThread t0 = new MyThread();
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
MyThread t4 = new MyThread();
MyThread t5 = new MyThread();
MyThread t6 = new MyThread();
MyThread t7 = new MyThread();
MyThread t8 = new MyThread();
MyThread t9 = new MyThread(); t0.start();
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
t7.start();
t8.start();
t9.start(); }
}

2、多线程put时可能导致元素丢失

原因:当多个线程同时执行addEntry(hash,key ,value,i)时,如果产生哈希碰撞,导致两个线程得到同样的bucketIndex去存储,就可能会发生元素覆盖丢失的情况

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);
if (size++ >= threshold)
resize(2 * table.length);
}

建议:

使用Hashtable 类,Hashtable 是线程安全的;

使用并发包下的java.util.concurrent.ConcurrentHashMap,ConcurrentHashMap实现了更高级的线程安全;

或者使用synchronizedMap() 同步方法包装 HashMap object,得到线程安全的Map,并在此Map上进行操作。

HashMap在高并发下如果没有处理线程安全会有怎样的安全隐患,具体表现是什么的更多相关文章

  1. HashMap在高并发下引起的死循环

    HashMap事实上并非线程安全的,在高并发的情况下,是非常可能发生死循环的,由此造成CPU 100%,这是非常可怕的.所以在多线程的情况下,用HashMap是非常不妥当的行为,应採用线程安全类Con ...

  2. HashMap 在高并发下引起的死循环

    HashMap 基本实现(JDK 8 之前) HashMap 通常会用一个指针数组(假设为 table[])来做分散所有的 key,当一个 key 被加入时,会通过 Hash 算法通过 key 算出这 ...

  3. HashMap高并发下存在的问题

    原文链接:https://blog.csdn.net/bjwfm2011/article/details/81076736 1.什么是HashMap? HashMap底层原理 HashMap是存储键值 ...

  4. JDK1.7 ConcurrentHashMap--解决高并发下的HashMap使用问题

    高并发下也可以使用HashTable .Collections.synchronizedMap因为他们是线程安全的,但是却牺牲了性能,无论是读操作.写操作都是给整个集合加锁,导致同一时间内其他操作均为 ...

  5. JDK1.7 高并发下的HashMap

    HashMap的容量是有限的.当经过多次元素插入,使得HashMap达到一定饱和度时,Key映射位置发生冲突的几率会逐渐提高. 这时候,HashMap需要扩展它的长度,也就是进行Resize. 影响发 ...

  6. 对HashMap的理解(二):高并发下的HashMap

    在分析hashmap高并发场景之前,我们要先搞清楚ReHash这个概念.ReHash是HashMap在扩容时的一个步骤.HashMap的容量是有限的.当经过多次元素插入,使得HashMap达到一定饱和 ...

  7. 高并发下,HashMap会产生哪些问题?

    HashMap在高并发环境下会产生的问题 HashMap其实并不是线程安全的,在高并发的情况下,会产生并发引起的问题: 比如: HashMap死循环,造成CPU100%负载 触发fail-fast 下 ...

  8. 高并发下的Java数据结构(List、Set、Map、Queue)

    由于并行程序与串行程序的不同特点,适用于串行程序的一些数据结构可能无法直接在并发环境下正常工作,这是因为这些数据结构不是线程安全的.本节将着重介绍一些可以用于多线程环境的数据结构,如并发List.并发 ...

  9. Java高并发下多线程编程

    1.创建线程 Java中创建线程主要有三种方式: 继承Thread类创建线程类: 定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务.因此也把run方法称为 ...

随机推荐

  1. 调用start()方法和直接调用run()方法的区别

    调用start()方法和直接调用run()方法的区别 新建一个线程,只需要使用new关键字创建一个线程对象,并且调用start()方法即可. Thread thread = new Thread(); ...

  2. OC语言大总结(下)

    根据OC学习的知识点,总结了一下,希望能帮到大家! 作者:韩俊强   未经允许,请勿转载! 关注博主:http://weibo.com/hanjunqiang 上接:http://blog.sina. ...

  3. 浅谈SystemClock 和Thead的区别和联系

    其实将SystemClock 和Thead直接放在一起是不合适的,我们首先来看下他们所在的api. public final class SystemClock extends Object java ...

  4. libgdx 1.4.1发布

    (转载自http://www.libgdx.cn/topic/4/libgdx-1-4-1%E5%8F%91%E5%B8%83) libgdx从未停止进步的脚步.10月10日,libgdx1.4.1发 ...

  5. android的Devices窗口中Online显示成Offline

    这种情况几率很低,如果出现,点击Reset adb就好了.

  6. 通过COM组件方式实现java调用C#写的DLL文件

    转自这里 最近一段时间单位在做一个Web项目,工程师用JAVA语言,需要公用人员信息,统一用户名和密码,原有的平台中是用C#语言开发的,在网上查找解决方法,通过JAVA调用C#的DLL文件实现.网上资 ...

  7. 新版MATERIAL DESIGN 官方动效指南(一)

    Google 刚发布了新版Material Design 官方动效指南,全文包括三个部分:为什么说动效很重要?如何制作优秀的Material Design动效及转场动画,动效的意义.新鲜热辣收好不谢! ...

  8. Android进阶(十九)AndroidAPP开发问题汇总(三)

    Android进阶(十九)AndroidAPP开发问题汇总(三) Java解析XML的几种方式: http://inotgaoshou.iteye.com/blog/1012188 从线程返回数据的两 ...

  9. Oracle EBS 预警系统管理(可用于配置工作流发审批邮件)

    本章主要讲述配置和设置Oracle EBS预警系统管理, 它比较方便和及时发用户或系统对数据库操作情况.下面讲一操作步聚: 1.预警系统管理-->系统-->选项 名称"Unix ...

  10. source insight 中tab键的设置

    转:http://xinzero.com/source-insight-code-alignment-ended.html source insight代码对齐Tab键终极版 以前也写过一个sourc ...