HashMap非线程安全分析
发布日期:2021-06-29 18:31:04
浏览次数:2
分类:技术文章
本文共 2336 字,大约阅读时间需要 7 分钟。
通过各方资料了解,HashMap不是线程安全的,但是为什么不是线程安全的,在什么情况下会出现问题呢?
1. 下面对HashMap做一个实验,两个线程,并发写入不同的值,key和value相同,最后再看看value和key是否相等。
import java.util.HashMap;public class TestHashMap { public static final HashMaphashMap = new HashMap (); public static void main(String[] args) throws InterruptedException { // 线程一 Thread t1 = new Thread() { public void run() { for (int i = 0; i < 25; i++) { hashMap.put(String.valueOf(i), String.valueOf(i)); } } }; // 线程二 Thread t2 = new Thread() { public void run() { for (int j = 25; j < 50; j++) { hashMap.put(String.valueOf(j), String.valueOf(j)); } } }; t1.start(); t2.start(); // 主线程休眠1秒钟,以便t1和t2两个线程将firstHashMap填装完毕。 Thread.sleep(1000); for (int i = 0; i < 50; i++) { // 如果key和value不同,说明在两个线程put的过程中出现异常。 if (!String.valueOf(i).equals(hashMap.get(String.valueOf(i)))) { System.err.println("出现多线程异常,序号:"+i); } } }}
经过多次测试,都会出现类似下面的错误:
出现多线程异常,序号:0
出现多线程异常,序号:1 出现多线程异常,序号:3 出现多线程异常,序号:42. 为什么会导致这样的情况
1) 查看HashMap的put方法
public V put(K key, V value) { if (key == null) return putForNullKey(value); int hash = hash(key.hashCode()); int i = indexFor(hash, table.length); for (Entrye = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key, value, i); return null; }
因为put方法没有加synchronized方法,在执行modCount++,addEntry时都有可能出现问题,modCount代码比较简单,就不深究了,下面再看看addEntry函数。
2)addEntry函数
void addEntry(int hash, K key, V value, int bucketIndex) { Entrye = table[bucketIndex]; table[bucketIndex] = new Entry (hash, key, value, e); if (size++ >= threshold) resize(2 * table.length); }
当容量达到阈值时,就会对map进行扩容,然后将原有值拷贝到新的值中;可以想象,如果两个线程同时对map进行扩容,将会带来巨大的问题,如数据丢失。
基于这点原因考虑,如果map本身的大小就比较大,不会扩容,那情况如何?
修改上述代码样例中的hashMap的构造函数,带上初始大小
public static final HashMaphashMap = new HashMap (50);
再次测试,基本没有出现并发的问题。
不过理论上看应该还是有问题的,只是出现的几率减小了,对于多线程情况下,可以使用HashTable或者通过java.util.Collections.synchronizedMap(map)函数对map进行封装或者使用ConcurrentHashMap类
参考资料:
转载地址:https://cxyxy.blog.csdn.net/article/details/24184751 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
不错!
[***.144.177.141]2024年04月09日 10时56分33秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
图像二值化----otsu(最大类间方差法、大津算法)
2019-04-29
图像二值化----otsu(最大类间方差法、大津算法)(二)
2019-04-29
OpenCV编程案例:使用轮廓函数检测连通区域
2019-04-29
opencv使用cvFindContours提取联通域
2019-04-29
C++中MessageBox的常见用法
2019-04-29
ordfilt2函数功能说明
2019-04-29
在图像变换中用最小二乘法求解仿射变换参数
2019-04-29
软件包应用分享|基于RT-Thread的百度语音识别(一)
2019-04-29
12月8日 RCEA - RT-Thread能力认证考试考前通知
2019-04-29
论坛热贴 | RT-Thread音频驱动开发(一)
2019-04-29
基于 Keil MDK 移植 RT-Thread Nano
2019-04-29
【报名截至今晚】12月14日深圳嵌入式与音频开发专题会议预告
2019-04-29
移植 RT-Thread Nano 到 RISC-V
2019-04-29
软件包应用分享|基于RT-Thread的百度语音识别(二)
2019-04-29
在 RT-Thread Nano 上添加控制台与 FinSH
2019-04-29
一站式开发工具:RT-Thread Studio 正式发布
2019-04-29
留言有礼|谢谢你悄悄点了小星星,让我们跃居GitHub RTOS Star榜第一
2019-04-29
功能更新!C 函数也能在 MicroPython 中被调用啦
2019-04-29
东软载波携ES32+RT-Thread走进海尔集团
2019-04-29
今晚8点直播预告:RT-Thread Studio等相关主题答疑
2019-04-29