四种方法使Map线程安全

四种方法使Map线程安全

如果需要使 Map 线程安全,大致有这么四种方法:

1、使用 synchronized 关键字,这也是最原始的方法。代码如下

synchronized(anObject) {
     value = map.get(key);
}

JDK1.2 提供了 Collections.synchronizedMap(originMap) 方法,同步方式其实和上面这段代码相同。

2、使用 JDK1.5 提供的锁(java.util.concurrent.locks.Lock)。代码如下

lock.lock();
value = map.get(key);
lock.unlock(); 

3、实际应用中,可能多数操作都是读操作,写操作较少。

针对这种情况,可以使用 JDK1.5 提供的读写锁(java.util.concurrent.locks.ReadWriteLock)。代码如下

rwlock.readLock().lock();
value = map.get(key);
rwlock.readLock().unlock(); 

这样两个读操作可以同时进行,理论上效率会比方法 2 高。

4、使用 JDK1.5 提供的 java.util.concurrent.ConcurrentHashMap 类。

该类将 Map 的存储空间分为若干块,每块拥有自己的锁,大大减少了多个线程争夺同一个锁的情况。代码如下

value = map.get(key); //同步机制内置在 get 方法中  

写了段测试代码,针对这四种方式进行测试,结果见附图。

测试内容为 1 秒钟所有 get 方法调用次数的总和。为了比较,增加了未使用任何同步机制的情况(非安全!)。理论上,不同步应该最快。

更多线程时,CPU 利用率提高,但增加了线程调度的开销,测试结果与五个线程差不多。

从附图可以看出:

  1. 不同步确实最快,与预期一致。
  2. 四种同步方式中,ConcurrentHashMap 是最快的,接近不同步的情况。
  3. synchronized 关键字非常慢,比使用锁慢了两个数量级。真是大跌眼镜,我很迷惑为什会 synchronized 慢到这个程度。
  4. 使用读写锁的读锁,比普通所稍慢。这个比较意外,可能硬件或测试代码没有发挥出读锁的全部功效。

结论:

  1. 如果 ConcurrentHashMap 够用,则使用 ConcurrentHashMap
  2. 如果需自己实现同步,则使用 JDK1.5 提供的锁机制,避免使用 synchronized 关键字。
时间: 2024-10-29 21:12:13

四种方法使Map线程安全的相关文章

java map遍历的四种方法总结_java

整理了关于java中map的遍历的四种方法: import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.Map.Entry;import java.util.Set;publicclassMapTest{privateMap<String,String> map;publicMapTest(){  map =newHashMap<String,String>();

如何对硬盘进行病毒检测的四种方法

要进行传染,必然会留下痕迹.生物医学病毒如此,电脑病毒也是一样.检测电脑病毒,就要到病毒寄生场所去检查,发现异常情况,并进而验明"正身",确认电脑病毒的存在.电脑病毒静态时存储于硬盘中,被激活时驻留在内存中,因此对电脑病毒的检测可以分为对硬盘的检测和对内存的检测. 一般对硬盘进行病毒检测时,要求内存中不带病毒,因为某些电脑病毒会向检测者报告假情况.例如"4096"病毒在内存中时,查看被它感染的文件,不会发现该文件的长度已发生变化,而当在内存中没有病毒时,才会发现文件

在PPT中插入Flash动画四种方法

  现在很多学科经常要做一些研究性学习或者调查报告,使用Powerpoint是个不错的主意. 而很多时候,我们需要添加一些flash动画来使我们的幻灯片更加生动.美观和具有说服力.但是Powerpoint中没有提供类似插入图片那样直接的功能.那么如何在PPT中插入flash动画影片呢? 下面我来教你四种方法: 方法一 将扩展名为. SWF的Flash动画文件插入PPT ---插入一个由文件创建的对象 ---在"动作设置"中的"对象动作"选项中选择"激活内容

详解Android提交数据到服务器的两种方式四种方法_Android

Android应用开发中,会经常要提交数据到服务器和从服务器得到数据,本文主要是给出了利用http协议采用HttpClient方式向服务器提交数据的方法. 代码比较简单,这里不去过多的阐述,直接看代码. /** * @author Dylan * 本类封装了Android中向web服务器提交数据的两种方式四种方法 */ public class SubmitDataByHttpClientAndOrdinaryWay { /** * 使用get请求以普通方式提交数据 * @param map 传

获得内核函数地址的四种方法

获得内核函数地址的四种方法   本文以获取内核函数 sys_open()的地址为例.   1)从System.map文件中直接得到地址:      $ grep sys_open /usr/src/linux/System.map      2)使用 nm 命令:      $ nm vmlinuz | grep sys_open      3)从 /proc/kallsyms 文件获得地址:      $ cat /proc/kallsyms | grep sys_open      4)使用

详解Android提交数据到服务器的两种方式四种方法

Android应用开发中,会经常要提交数据到服务器和从服务器得到数据,本文主要是给出了利用http协议采用HttpClient方式向服务器提交数据的方法. 代码比较简单,这里不去过多的阐述,直接看代码. /** * @author Dylan * 本类封装了Android中向web服务器提交数据的两种方式四种方法 */ public class SubmitDataByHttpClientAndOrdinaryWay { /** * 使用get请求以普通方式提交数据 * @param map 传

在Windows 8 PC上安装Linux的四种方法

微软RTM版本的Windows 8相信已经有很多人试用过了,如果在Windows 8 PC上安装Linux很困难,那我们该怎么办呢?下面提供四种方法. 在UEFI上启动Linux 首先,需要在UEFI上启动Linux.因为除了Mac,很少有PC使用UEFI替换BIOS,所以大家都不怎么关心从UEFI启动Linux. 现在,很多想在Mac上运行Linux的人使用兼容支持模块CSM,提供Mac上BIOS的仿真.这种方式很麻烦,运行得不好,在Secure Boot Windows 8 PC上可能会更糟

如何查看mysql版本的四种方法

菜鸟大讲堂:如何查看mysql版本的四种方法 1:在终端下:mysql -V. 以下是代码片段: [shengting@login ~]$ mysql -V mysql Ver 14.7 Distrib 4.1.10a, for redhat-linux-gnu (i686) 2:在mysql中:mysql> status; 以下是代码片段: mysql> status; -------------- mysql Ver 14.7 Distrib 4.1.10a, for redhat-lin

Excel 2000访问远程数据的四种方法

excel|访问|数据      Excel 2000作为一个电子表格软件,它不仅有强大的数据处理能力,而且它的报表功能也是十分强大.因而常常用Excel 2000去调用Access.SQL Server.Oracle.DB2等数据库软件建立的大型数据库的内容.用户可以在工作表中对这些数据进行筛选.排序.查询.编辑和打印报表,十分方便,这也是大多数人都熟悉的.但如何去调用这数据呢?本人在这里提供4种方法.    下面四种方法必须要先创建一个数据源,我们以SQL Server7.0内的样本数据库p