Java 非线程安全的HashMap如何在多线程中使用

HashMap 是非线程安全的。在多线程条件下,容易导致死循环,具体表现为CPU使用率100%。因此多线程环境下保证 HashMap 的线程安全性,主要有如下几种方法:

  1. 使用 java.util.Hashtable 类,此类是线程安全的。
  2. 使用 java.util.concurrent.ConcurrentHashMap,此类是线程安全的。
  3. 使用 java.util.Collections.synchronizedMap() 方法包装 HashMap object,得到线程安全的Map,并在此Map上进行操作。
  4. 自己在程序的关键代码段加锁,保证多线程安全(不推荐)

接下来分析上面列举的几种方法实现并发安全的 HashMap 的原理:

(一)java.util.Hashtable类:

查看该类的源码

  1. public synchronized V get(Object key) {
  2. …… //具体的实现省略,请参考 jdk实现
  3. }
  4.  
  5. public synchronized V put(K key, V value) {
  6. …… //具体的实现省略,请参考 jdk实现
  7. }
  8.  
  9. public synchronized V remove(Object key) {
  10. …… //具体的实现省略,请参考 jdk实现
  11. }

上面是 Hashtable 类提供的几个主要方法,包括 get(),put(),remove() 等。注意到每个方法本身都是 synchronized 的,不会出现两个线程同时对数据进行操作的情况,因此保证了线程安全性,但是也大大的降低了执行效率。因此是不推荐的。

(二)使用 java.util.concurrent.ConcurrentHashMap 类:

该类是 HashMap 的线程安全版,与 Hashtable 相比, ConcurrentHashMap 不仅保证了访问的线程安全性,而且在效率上有较大的提高。

ConcurrentHashMap的数据结构如下:

可以看出,相对 HashMap 和 Hashtable, ConcurrentHashMap 增加了Segment 层,每个Segment 原理上等同于一个 Hashtable, ConcurrentHashMap 等同于一个 Segment 的数组。下面是 ConcurrentHashMap 的 put 和 get 方法:

  1. final Segment<K,V> segmentFor(int hash) {
  2. return segments[(hash >>> segmentShift) & segmentMask];
  3. }
  4.  
  5. public V put(K key, V value) {
  6. if (value == null)
  7. throw new NullPointerException();
  8. int hash = hash(key.hashCode());
  9. return segmentFor(hash).put(key, hash, value, false);
  10. }
  11.  
  12. public V get(Object key) {
  13. int hash = hash(key.hashCode());
  14. return segmentFor(hash).get(key, hash);
  15. }

向 ConcurrentHashMap 中插入数据(put) 或者 读取数据(get),首先都要将相应的 Key 映射到对应的 Segment,因此不用锁定整个类, 只要对单个的 Segment 操作进行上锁操作就可以了。理论上如果有 n 个 Segment,那么最多可以同时支持 n 个线程的并发访问,从而大大提高了并发访问的效率。

Java 非线程安全的HashMap如何在多线程中使用的更多相关文章

  1. 非线程安全的HashMap 和 线程安全的ConcurrentHashMap

    在平时开发中,我们经常采用HashMap来作为本地缓存的一种实现方式,将一些如系统变量等数据量比较少的参数保存在HashMap中,并将其作为单例类的一个属性.在系统运行中,使用到这些缓存数据,都可以直 ...

  2. [Java集合] 彻底搞懂HashMap,HashTable,ConcurrentHashMap之关联.

    注: 今天看到的一篇讲hashMap,hashTable,concurrentHashMap很透彻的一篇文章, 感谢原作者的分享. 原文地址: http://blog.csdn.net/zhanger ...

  3. Java并发基础08. 造成HashMap非线程安全的原因

    在前面我的一篇总结(6. 线程范围内共享数据)文章中提到,为了数据能在线程范围内使用,我用了 HashMap 来存储不同线程中的数据,key 为当前线程,value 为当前线程中的数据.我取的时候根据 ...

  4. JAVA中的线程安全与非线程安全

    原文:http://blog.csdn.net/xiao__gui/article/details/8934832 ArrayList和Vector有什么区别?HashMap和HashTable有什么 ...

  5. java 多线程 线程安全及非线程安全的集合对象

    一.概念: 线程安全:就是当多线程访问时,采用了加锁的机制:即当一个线程访问该类的某个数据时,会对这个数据进行保护,其他线程不能对其访问,直到该线程读取完之后,其他线程才可以使用.防止出现数据不一致或 ...

  6. Java多线程之非线程安全

    在Java多线程中我会重点总结五个如下的技术点: 1.非线程安全是如何出现的 2.synchronized对象监视器为Objec时的使用 3.synchronized对象监视器为Class时的使用 4 ...

  7. java中线程安全和非线程安全的集合

    线程安全 非线程安全 Collection Vector ArrayList.LinkedList HashSet.TreeSet Map HashTable HashMap.TreeMap 字符串 ...

  8. Java线程安全和非线程安全

    ArrayList是非线程安全的,Vector是线程安全的:HashMap是非线程安全的,HashTable是线程安全的:StringBuilder是非线程安全的,StringBuffer是线程安全的 ...

  9. 为什么JAVA虚拟机分为线程共享和非线程共享?

    大多数 JVM 将内存区域划分为 Method Area(Non-Heap)(方法区) ,Heap(堆) , Program Counter Register(程序计数器) , VM Stack(虚拟 ...

随机推荐

  1. Java设计模式之策略设计模式

    1.什么是-策略设计模式 在软件开发中常常遇到这种情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能.如查找.排序等,一种常用的方法是硬编码(Ha ...

  2. Microsoft Visual Studio | VS打开解决方案时加载失败,或者出现错误提示

    Microsoft Visual Studio | VS打开解决方案时加载失败,或者出现错误提示 1.加载失败并且输出状态栏也没什么错误提示的话,往往是因为一个低版本VS2010.VS2012等打开了 ...

  3. 登录界面 Android简单http get请求(含server端)五 iOS端(特别篇)

    </pre><pre name="code" class="objc">NSDictionary *dict=@{@"user ...

  4. 摧枯拉朽,说说ES6的三把火

    阅读目录 我是 Jser 我骄傲 作用域 模块系统 类(Class) 我是 Jser 我骄傲 JavaScript 如今可谓是屌丝逆袭高富帅的代名词哈,从当初闹着玩似的诞生到现在 Github 上力压 ...

  5. 超详细的 Linux CentOS yum 源的配置与使用【转发+新增】

    一.yum 简介 yum,是Yellow dog Updater, Modified 的简称,是杜克大学为了提高RPM 软件包安装性而开发的一种软件包管理器.起初是由yellow dog 这一发行版的 ...

  6. 自学Zabbix3.7-事件Event

    配置item.trigger.都是为发送报警做准备的,什么是事件通知呢?简单的说故障发生了,zabbix会发邮件或者短信给你,告诉你服务器的一些状况. 1. 通知条件 发送通知,需要有如下步骤 定义一 ...

  7. idea将maven项目打包成war包的方式,以及使用war包

    打包WAR过程 首先对项目进行编译.然后执行以下步骤: 单击下图红色方框处  在IDEA右侧出现maven project选项  单击maven project选项,出现Spring MVC Basi ...

  8. JAVA提高二十:CopyOnWriteArrayList&CopyOnWriteArraySet&ConcurrentHashMap介绍

    前面我们将java集合类的大部分类都进行了深入分析,但我们会发现一个共性问题就是并发的问题,那么如何解决呢?我们前面基本都是通过Collections的一个工具类来进行的解决,但实际大部分使用中人们普 ...

  9. iOS Swift 模块练习/swift基础学习

    SWIFT项目练习     SWIFT项目练习2 iOS Swift基础知识代码 推荐:Swift学习使用知识代码软件 0.swift中的宏定义(使用方法代替宏) 一.视图  +控件 1.UIImag ...

  10. ios 访问隐私信息 info.plist 中的字段

    1.iOS10相册相机闪退bug: iOS10系统下调用系统相册,相机功能,遇到闪退的情况,描述如下: This app has crashed because it attempted to acc ...