为什么说 HashMap 是非线程安全的?
我们在学习 HashMap 的时候,都知道 HashMap 是非线程安全的,同时我们知道 HashTable 是线程安全的,因为里面的方法使用了 synchronized 进行同步。
但是 HashMap 为什么是非线程安全的呢?难道仅仅就是因为内部的方法没有 synchronized 关键字修饰吗?这篇文章主要来分析一下原因。
我们知道 HashMap 底层是一个 Entry 数组,当发生 hash 冲突的时候,HashMap 是采用链表的方式来解决的,在对应的数组位置存放链表的头结点。对链表而言,新加入的节点会从头结点加入。
1、HashMap 在插入的时候
现在假如 A 线程和 B 线程同时进行插入操作,然后计算出了相同的哈希值对应了相同的数组位置,因为此时该位置还没数据,然后对同一个数组位置,两个线程会同时得到现在的头结点,然后 A 写入新的头结点之后,B 也写入新的头结点,那B的写入操作就会覆盖 A 的写入操作造成 A 的写入操作丢失。
2、HashMap 在扩容的时候
HashMap 有个扩容的操作,这个操作会新生成一个新的容量的数组,然后对原数组的所有键值对重新进行计算和写入新的数组,之后指向新生成的数组。
那么问题来了,当多个线程同时进来,检测到总数量超过门限值的时候就会同时调用 resize 操作,各自生成新的数组并 rehash 后赋给该 map 底层的数组,结果最终只有最后一个线程生成的新数组被赋给该 map 底层,其他线程的均会丢失。
3、HashMap 在删除数据的时候
删除这一块可能会出现两种线程安全问题,第一种是一个线程判断得到了指定的数组位置i并进入了循环,此时,另一个线程也在同样的位置已经删掉了i位置的那个数据了,然后第一个线程那边就没了。但是删除的话,没了倒问题不大。
再看另一种情况,当多个线程同时操作同一个数组位置的时候,也都会先取得现在状态下该位置存储的头结点,然后各自去进行计算操作,之后再把结果写会到该数组位置去,其实写回的时候可能其他的线程已经就把这个位置给修改过了,就会覆盖其他线程的修改。
其他地方还有很多可能会出现线程安全问题,我就不一一列举了,总之 HashMap 是非线程安全的,有并发问题时,建议使用 ConcrrentHashMap。
为什么说 HashMap 是非线程安全的?的更多相关文章
- hashMap的线程不安全
hashMap是非线程安全的,表现在两种情况下: 1 扩容: t1线程对map进行扩容,此时t2线程来读取数据,原本要读取位置为2的元素,扩容后此元素位置未必是2,则出现读取错误数据. 2 hash碰 ...
- HashMap变成线程安全方法
我们都知道.HashMap是非线程安全的(非同步的).那么怎么才能让HashMap变成线程安全的呢? 我认为主要可以通过以下三种方法来实现: 1.替换成Hashtable,Hashtable通过对整个 ...
- Java并发基础08. 造成HashMap非线程安全的原因
在前面我的一篇总结(6. 线程范围内共享数据)文章中提到,为了数据能在线程范围内使用,我用了 HashMap 来存储不同线程中的数据,key 为当前线程,value 为当前线程中的数据.我取的时候根据 ...
- 非线程安全的HashMap 和 线程安全的ConcurrentHashMap
在平时开发中,我们经常采用HashMap来作为本地缓存的一种实现方式,将一些如系统变量等数据量比较少的参数保存在HashMap中,并将其作为单例类的一个属性.在系统运行中,使用到这些缓存数据,都可以直 ...
- 如何判断PHP 是线程安全还是非线程安全的
什么是线程安全与非线程安全? 线程安全就是在多线程环境下也不会出现数据不一致,而非线程安全就有可能出现数据不一致的情况. 线程安全由于要确保数据的一致性,所以对资源的读写进行了控制,换句话说增加了系统 ...
- HashMap为什么线程不安全(hash碰撞与扩容导致)
一直以来都知道HashMap是线程不安全的,但是到底为什么线程不安全,在多线程操作情况下什么时候线程不安全? 让我们先来了解一下HashMap的底层存储结构,HashMap底层是一个Entry数组,一 ...
- Java基础知识强化之集合框架笔记80:HashMap的线程不安全性的体现
1. HashMap 的线程不安全性的体现: 主要是下面两方面: (1)多线程环境下,多个线程同时resize()时候,容易产生死锁现象.即:resize死循环 (2)如果在使用迭代器的过程中有其他线 ...
- 面试官:小伙子,你给我说一下HashMap 为什么线程不安全?
前言:我们都知道HashMap是线程不安全的,在多线程环境中不建议使用,但是其线程不安全主要体现在什么地方呢,本文将对该问题进行解密. 1.jdk1.7中的HashMap 在jdk1.8中对HashM ...
- HashMap 为什么线程不安全?
作者:developer http://cnblogs.com/developer_chan/p/10450908.html 我们都知道HashMap是线程不安全的,在多线程环境中不建议使用,但是其线 ...
随机推荐
- layui透明弹框
效果: layui.use('layer', function () { var layer = layui.layer; var str = '<div>'; str += '<d ...
- 关于Sublime Text3的emmet插件和tab快捷键冲突问题
当使用Sublime text3时会遇到快捷键冲突的问题,其中就有安装Emmet之后,tab无法缩进了, 网上有些说看看Browse Packages目录下是否有PyV8插件安装,该插件一般情况下随E ...
- Eclipse + Pydev问题 : pydev unresolved import
http://blog.csdn.net/qq_22765745/article/details/71054030http://blog.csdn.net/amghost/article/detail ...
- 仿豆瓣网(电脑版网页)HTML+CSS实现
步骤一:将豆瓣电脑版网页以图片形式保存下来: 利用了chrome里面的插件: 步骤二:将图片放置到PS中,研究布局: 我将其分为header部分,banner部分,section部分,footer部分 ...
- mark_save
class BookConfig(ModelStark): def edit(self, obj=None, is_header=False): if is_header: return " ...
- python单下划线与双下划线的区别
Python 用下划线作为变量前缀和后缀指定特殊变量. _xxx 不能用'from moduleimport *'导入 __xxx__ 系统定义名字 __xxx 类中的私有变量名 核心风格:避免用下划 ...
- flask 使用Flask-WTF处理表单
使用Flask-WTF处理表单 扩展Flask-WTF继承了WTFforms,使用它可以在flask中更方便的使用WTForms.Flask-WTF将表单数据解析.CSRF保护.文件上传等功能与Fla ...
- 转:C# 对委托的BeginInvoke,EndInvoke 及Control 的BeginInvoke,EndInvoke 的理解
转载自:http://www.cnblogs.com/easyfrog/p/3141269.html using System; using System.Collections.Generic; u ...
- Step4:SQL Server 跨网段(跨机房)复制
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 解决方案(Solution) 搭建过程(Process) 注意事项(Attention) 参考 ...
- 10分钟看懂!基于Zookeeper的分布式锁
实现分布式锁目前有三种流行方案,分别为基于数据库.Redis.Zookeeper的方案,其中前两种方案网络上有很多资料可以参考,本文不做展开.我们来看下使用Zookeeper如何实现分布式锁. 什么是 ...