Map 的线程安全问题

本贴最后更新于 3323 天前,其中的信息可能已经事过境迁

如果需要使 Map 线程安全,大致有这么四种方法: 
1、使用 synchronized 关键字,代码如下 

Java代码  
  1. synchronized(anObject) {     
  2.     value = map.get(key);  
  3. }  

  

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

Java代码  
  1. lock.lock();     
  2. value = map.get(key);     
  3. lock.unlock();  

  

3、使用 JDK1.5 提供的读写锁(java.util.concurrent.locks.ReadWriteLock)。代码如下 

Java代码  
  1. rwlock.readLock().lock();     
  2. value = map.get(key);     
  3. rwlock.readLock().unlock();  

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

4、使用 JDK1.5 提供的 java.util.concurrent.ConcurrentHashMap 类。该类将 Map 的存储空间分为若干块,每块拥有自己的锁,大大减少了多个线程争夺同一个锁的情况。代码如下 
value = map.get(key); //同步机制内置在 get 方法中 

比较: 

1、不同步确实最快,与预期一致。 
2、四种同步方式中,ConcurrentHashMap 是最快的,接近不同步的情况。 
3、synchronized 关键字非常慢,比使用锁慢了两个数量级。如果需自己实现同步,则使用 JDK1.5 提供的锁机制,避免使用 synchronized 关键字。 

Java代码  
  1. public class MapTest{     
  2.     public static final int THREAD_COUNT = 1;     
  3.     public static final int MAP_SIZE = 1000;     
  4.     public static final int EXECUTION_MILLES = 1000;     
  5.     public static final int[] KEYS = new int[100];            
  6.     public static void main(String[] args) throws Exception{     
  7.   
  8.         //初始化     
  9.         Random rand = new Random();     
  10.         for (int i = 0; i < KEYS.length; ++i)  KEYS[i] = rand.nextInt();     
  11.      //创建线程     
  12.       long start = System.currentTimeMillis();     
  13.       Thread[] threads = new Thread[THREAD_COUNT];     
  14.       for (int i = 0; i < THREAD_COUNT; ++i) {     
  15.           threads[i] = new SynchronizedThread();     
  16.           //threads[i] = new LockThread();     
  17.            threads[i].start();     
  18.       }     
  19.   
  20.        //等待其它线程执行若干时间     
  21.         Thread.sleep(EXECUTION_MILLES);  
  22.         //统计 get 操作的次数     
  23.         long sum = 0;            
  24.         for (int i = 0; i < THREAD_COUNT; ++i){     
  25.         sum += threads[i].getClass().getDeclaredField("count").getLong(threads[i]);           }     
  26.         long millisCost = System.currentTimeMillis() - start;     
  27.         System.out.println(sum + "(" + (millisCost) + "ms)");     
  28.         System.exit(0);     
  29.     }     
  30.          
  31.     public static void fillMap(Map<Integer, Integer> map){     
  32.         Random rand = new Random();  
  33.         for (int i = 0; i < MAP_SIZE; ++i){     
  34.             map.put(rand.nextInt(), rand.nextInt());     
  35.         }     
  36.     }     
  37. }     
  38. class SynchronizedThread extends Thread{     
  39.     private static Map<Integer, Integer> map = new HashMap<Integer, Integer>();      
  40.     public long count = 0;  
  41.     static {     
  42.         MapTest.fillMap(map);     
  43.     }     
  44.     public void run()  {     
  45.         for (;;) {     
  46.             int index = (int)(count % MapTest.KEYS.length);     
  47.             synchronized(SynchronizedThread.class){     
  48.                 map.get(MapTest.KEYS[index]);     
  49.             }     
  50.             ++count;     
  51.         }     
  52.     }     
  53. }     
  54.   
  55.   
  56.   
  57. class LockThread extends Thread{     
  58.     private static Map<Integer, Integer> map = new HashMap<Integer, Integer>();      
  59.     private static Lock lock = new ReentrantLock();     
  60.     public long count = 0;           
  61.     static {     
  62.         MapTest.fillMap(map);     
  63.     }            
  64.     public void run() {     
  65.         for (;;) {     
  66.             int index = (int)(count % MapTest.KEYS.length);     
  67.             lock.lock();     
  68.             map.get(MapTest.KEYS[index]);     
  69.             lock.unlock();     
  70.             ++count;     
  71.         }     
  72.     }     
  73. }  




以下两种写法的区别: 

Java代码  
  1. synchronized(anObject)    
  2. {    
  3.     value = map.get(key);    
  4. }  
  5. synchronized(anObject)    
  6. {    
  7.     map.put(key, value);    
  8. }  


这样因该是线程安全的,只要保证put和get都同步到这个anObject上来 

Java代码  
  1. synchronized(key)    
  2. {    
  3.     value = map.get(key);    
  4. }   
  5. synchronized(key)    
  6. {    
  7.     map.put(key, value);   
  8. }  


这种写法可能会有问题,因为get和put的key可能是不同的对象

  • 线程
    123 引用 • 111 回帖 • 3 关注
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3200 引用 • 8215 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • Sillot

    Insights(注意当前设置 master 为默认分支)

    汐洛彖夲肜矩阵(Sillot T☳Converbenk Matrix),致力于服务智慧新彖乄,具有彖乄驱动、极致优雅、开发者友好的特点。其中汐洛绞架(Sillot-Gibbet)基于自思源笔记(siyuan-note),前身是思源笔记汐洛版(更早是思源笔记汐洛分支),是智慧新录乄终端(多端融合,移动端优先)。

    主仓库地址:Hi-Windom/Sillot

    文档地址:sillot.db.sc.cn

    注意事项:

    1. ⚠️ 汐洛仍在早期开发阶段,尚不稳定
    2. ⚠️ 汐洛并非面向普通用户设计,使用前请了解风险
    3. ⚠️ 汐洛绞架基于思源笔记,开发者尽最大努力与思源笔记保持兼容,但无法实现 100% 兼容
    29 引用 • 25 回帖 • 118 关注
  • Bootstrap

    Bootstrap 是 Twitter 推出的一个用于前端开发的开源工具包。它由 Twitter 的设计师 Mark Otto 和 Jacob Thornton 合作开发,是一个 CSS / HTML 框架。

    18 引用 • 33 回帖 • 645 关注
  • LeetCode

    LeetCode(力扣)是一个全球极客挚爱的高质量技术成长平台,想要学习和提升专业能力从这里开始,充足技术干货等你来啃,轻松拿下 Dream Offer!

    209 引用 • 72 回帖 • 1 关注
  • IDEA

    IDEA 全称 IntelliJ IDEA,是一款 Java 语言开发的集成环境,在业界被公认为最好的 Java 开发工具之一。IDEA 是 JetBrains 公司的产品,这家公司总部位于捷克共和国的首都布拉格,开发人员以严谨著称的东欧程序员为主。

    181 引用 • 400 回帖
  • Sym

    Sym 是一款用 Java 实现的现代化社区(论坛/BBS/社交网络/博客)系统平台。

    下一代的社区系统,为未来而构建

    524 引用 • 4601 回帖 • 706 关注
  • Hprose

    Hprose 是一款先进的轻量级、跨语言、跨平台、无侵入式、高性能动态远程对象调用引擎库。它不仅简单易用,而且功能强大。你无需专门学习,只需看上几眼,就能用它轻松构建分布式应用系统。

    9 引用 • 17 回帖 • 631 关注
  • BAE

    百度应用引擎(Baidu App Engine)提供了 PHP、Java、Python 的执行环境,以及云存储、消息服务、云数据库等全面的云服务。它可以让开发者实现自动地部署和管理应用,并且提供动态扩容和负载均衡的运行环境,让开发者不用考虑高成本的运维工作,只需专注于业务逻辑,大大降低了开发者学习和迁移的成本。

    19 引用 • 75 回帖 • 668 关注
  • webpack

    webpack 是一个用于前端开发的模块加载器和打包工具,它能把各种资源,例如 JS、CSS(less/sass)、图片等都作为模块来使用和处理。

    42 引用 • 130 回帖 • 250 关注
  • 服务器

    服务器,也称伺服器,是提供计算服务的设备。由于服务器需要响应服务请求,并进行处理,因此一般来说服务器应具备承担服务并且保障服务的能力。

    125 引用 • 585 回帖
  • TensorFlow

    TensorFlow 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。

    20 引用 • 19 回帖 • 3 关注
  • RemNote
    2 引用 • 16 回帖 • 10 关注
  • 域名

    域名(Domain Name),简称域名、网域,是由一串用点分隔的名字组成的 Internet 上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理位置)。

    43 引用 • 208 回帖
  • Chrome

    Chrome 又称 Google 浏览器,是一个由谷歌公司开发的网页浏览器。该浏览器是基于其他开源软件所编写,包括 WebKit,目标是提升稳定性、速度和安全性,并创造出简单且有效率的使用者界面。

    63 引用 • 289 回帖
  • Lute

    Lute 是一款结构化的 Markdown 引擎,支持 Go 和 JavaScript。

    28 引用 • 197 回帖 • 30 关注
  • 招聘

    哪里都缺人,哪里都不缺人。

    188 引用 • 1057 回帖
  • 大数据

    大数据(big data)是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。

    93 引用 • 113 回帖
  • iOS

    iOS 是由苹果公司开发的移动操作系统,最早于 2007 年 1 月 9 日的 Macworld 大会上公布这个系统,最初是设计给 iPhone 使用的,后来陆续套用到 iPod touch、iPad 以及 Apple TV 等产品上。iOS 与苹果的 Mac OS X 操作系统一样,属于类 Unix 的商业操作系统。

    89 引用 • 150 回帖
  • 微服务

    微服务架构是一种架构模式,它提倡将单一应用划分成一组小的服务。服务之间互相协调,互相配合,为用户提供最终价值。每个服务运行在独立的进程中。服务于服务之间才用轻量级的通信机制互相沟通。每个服务都围绕着具体业务构建,能够被独立的部署。

    96 引用 • 155 回帖 • 2 关注
  • 生活

    生活是指人类生存过程中的各项活动的总和,范畴较广,一般指为幸福的意义而存在。生活实际上是对人生的一种诠释。生活包括人类在社会中与自己息息相关的日常活动和心理影射。

    230 引用 • 1454 回帖
  • Visio
    1 引用 • 2 回帖 • 2 关注
  • SendCloud

    SendCloud 由搜狐武汉研发中心孵化的项目,是致力于为开发者提供高质量的触发邮件服务的云端邮件发送平台,为开发者提供便利的 API 接口来调用服务,让邮件准确迅速到达用户收件箱并获得强大的追踪数据。

    2 引用 • 8 回帖 • 495 关注
  • 开源

    Open Source, Open Mind, Open Sight, Open Future!

    411 引用 • 3588 回帖
  • Solo

    Solo 是一款小而美的开源博客系统,专为程序员设计。Solo 有着非常活跃的社区,可将文章作为帖子推送到社区,来自社区的回帖将作为博客评论进行联动(具体细节请浏览 B3log 构思 - 分布式社区网络)。

    这是一种全新的网络社区体验,让热爱记录和分享的你不再感到孤单!

    1441 引用 • 10069 回帖 • 496 关注
  • GAE

    Google App Engine(GAE)是 Google 管理的数据中心中用于 WEB 应用程序的开发和托管的平台。2008 年 4 月 发布第一个测试版本。目前支持 Python、Java 和 Go 开发部署。全球已有数十万的开发者在其上开发了众多的应用。

    14 引用 • 42 回帖 • 813 关注
  • App

    App(应用程序,Application 的缩写)一般指手机软件。

    91 引用 • 384 回帖
  • SQLServer

    SQL Server 是由 [微软] 开发和推广的关系数据库管理系统(DBMS),它最初是由 微软、Sybase 和 Ashton-Tate 三家公司共同开发的,并于 1988 年推出了第一个 OS/2 版本。

    21 引用 • 31 回帖
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3200 引用 • 8215 回帖