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类:

查看该类的源码

public synchronized V get(Object key) {
…… //具体的实现省略,请参考 jdk实现
} public synchronized V put(K key, V value) {
…… //具体的实现省略,请参考 jdk实现
} public synchronized V remove(Object key) {
…… //具体的实现省略,请参考 jdk实现
}

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

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

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

ConcurrentHashMap的数据结构如下:

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

final Segment<K,V> segmentFor(int hash) {
return segments[(hash >>> segmentShift) & segmentMask];
} public V put(K key, V value) {
if (value == null)
throw new NullPointerException();
int hash = hash(key.hashCode());
return segmentFor(hash).put(key, hash, value, false);
} public V get(Object key) {
int hash = hash(key.hashCode());
return segmentFor(hash).get(key, hash);
}

向 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. android 读取系统文件 wpa_supplicant

    1,须要权限 <uses-permission android:name="android.permission.ACCESS_SUPERUSER" /> 2,下载 R ...

  2. Chromium与CEF的多进程模型及相关參数

    CEF基于Chromium,也是多进程模型.关于进程模型.參考这里:https://www.chromium.org/developers/design-documents/process-model ...

  3. 杭电1513Palindrome

    Palindrome Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total ...

  4. keeplived日志位置指定

    作为一个运维DBA,除了关心数据库的关键指数.还得往架构和底层基础知识多靠拢. 2010年刚工作的时候,那会Cacti监控比較流行吧.可恶的是SNMP会把默认日志写到系统日志文件中面,导致排错时非常受 ...

  5. Struts2 2.5.12的问题

    使用maven搭建的Struts项目,使用Struts 2.5.12会启动报错,应该不是包冲突的问题,感觉是lang3.jar的问题,换回2.5.10.1就没事了. 这点挺奇怪的,不应该是jar包损坏 ...

  6. Java连接MySQL数据库增删改查通用方法

    版权声明:本文为博主原创文章,未经博主允许不得转载. Java连接MySQL数据库增删改查通用方法 运行环境:eclipse+MySQL 以前我们Java连接MySQL数据库都是一个数据库写一个类,类 ...

  7. 《Head First 设计模式》【PDF】下载

    <Head First 设计模式>[PDF]下载链接: https://u253469.ctfile.com/fs/253469-231196307 First 设计模式>[PDF] ...

  8. 字符串输入时的strlen()与\0

    在做串的数据结构时,被字符串printf %s输出时的结尾判断.strlen();长度.自定义StrCopy();字符串复制函数.StrAssign();字符串赋值函数卡了一下,固写此博巩固相关知识点 ...

  9. iOS控制器跳转动画

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 MyViewController *myVC = [[MyViewController alloc]init];  //创建动画  C ...

  10. 关于git的一些理论知识

    一.什么是版本控制器 好多刚用git的coder一说起git,就随口会说出版本控制器嘛,我问那是干嘛的,大部分人就回答上传代码的.然后会用,但是有些理论你问他们他们就不知道了,比如不是代码的文件就不能 ...