如何使用

概述

  • ConcurrentHashMap:

    线程安全;
    其将整个Hash桶进行了分段segment,也就是将这个大的数组分成了几个小的片段segment,而且每个小的片段segment上面都有锁存在,那么在插入元素的时候就要先找到应该插入到哪一个片段segment,然后再在这个片段上面进行插入,而且这里还需要获取segment锁(即锁分段技术);
    ConcurrentHashMap让锁的粒度更精细一些,并发性能更好

  • SynchronizedMap:

    线程安全;
    通过synchronized关键字进行同步控制;
    所有单个的操作都是线程安全的,但是多个操作组成的操作序列却可能导致数据争用,因为在操作序列中控制流取决于前面操作的结果。这也被称作是:有条件的线程安全性
    效率低

两者源码对比

  哈希表声明:通过下面两图对比可以发现,两者的区别在于volatile关键字


  • ConcurrentHashMap:

  • SynchronizedMap:

  put()方法:


  • ConcurrentHashMap:

  • SynchronizedMap:

  get()方法:


  • ConcurrentHashMap:

  • SynchronizedMap:

ConcurrentHashMap详解

  1. 与HashTable容器对比:HashTable容器在竞争激烈的并发环境下表现出效率底下的原因是所有访问HashTable的线程都必须竞争同一把锁(其实现是在对应的方法上添加了synchronized关键字进行修饰),那假如容器里有多把锁,每一把锁用于锁容器其中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效的提高并发效率,这就是ConcurrentHashMap所使用的锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。
  2. get()方法:其高效之处在于整个get过程不需要加锁,除非读到的值是空的才会加锁重读。get方法里将要使用的共享变量都定义成volatile,如用于统计当前Segement大小的count字段和用于存储值的HashEntry的value。定义成volatile的变量,能够在线程之间保持可见性,能够被多线程同时读,并且保证不会读到过期的值,但是只能被单线程写(有一种情况可以被线程写,就是写入的值不依赖于原值),在get操作里只需要读不需要写共享变量count和value,所以可以不用加锁。
  3. put()方法:首先定位到Segment,然后在Segment里进行插入操作。插入操作需要经历两个步骤,第一步判断是否需要对Segment里的HashEntry数组进行扩容,第二步定位添加元素的位置然后放在HashEntry数组里。
  4. 具体实现:在ConcurrentHashMap的实现中使用了一个包含16个锁的数组,每个锁保护所有散列桶的1/16,其中第N个散列桶由第(N mod 16)个锁来保护。假设散列函数具有合理的分布性,并且关键字能够实现均匀分布,那么这大约能把对于锁的请求减少到原来的1/16。正是这项技术使得其能够支持多达16个并发的写入器。
  5. 缺点:当ConcurrentHashMap需要扩展映射范围,以及重新计算键值得散列值要分布到更大的桶集合中时,就需要获取分段锁集合中所有的锁(要获取内置锁的一个集合,采用的唯一方式是递归)。

Java中SynchronizedMap与ConcurrentHashMap的对比的更多相关文章

  1. 关于Java 中Integer 和Long对象 对比的陷阱(简单却容易犯的错误)

    彩票客户端“忘记密码”功能有bug,今天调试时,发现了原因: 功能模块中有一段: if(userpo.getId()!=Long.valueOf(uid)){ throw new VerifyExce ...

  2. Java中HashMap与ConcurrentHashMap的区别

    从JDK1.2起,就有了HashMap,正如前一篇文章所说,HashMap不是线程安全的,因此多线程操作时需要格外小心. 在JDK1.5中,伟大的Doug Lea给我们带来了concurrent包,从 ...

  3. Java中的queue和deque对比详解

    队列(queue)简述 队列(queue)是一种常用的数据结构,可以将队列看做是一种特殊的线性表,该结构遵循的先进先出原则.Java中,LinkedList实现了Queue接口,因为LinkedLis ...

  4. Java7/8 中 HashMap 和 ConcurrentHashMap的对比和分析

    大家可能平时用HashMap比较多,相对于ConcurrentHashMap 来说并不是很熟悉.ConcurrentHashMap 是 JDK 1.5 添加的新集合,用来保证线程安全性,提升 Map ...

  5. Java中BufferedReader和scanner的对比

    Scanner 和BufferedReader同样能实现将键盘输入的数据送入程序, import java.io.*;import java.util.Scanner;public class C { ...

  6. [目录][总结] C++和Java 中的主要操作对比

    总结一些,C++ 和Java 中的一些常用操作对比,就当是自己的查询工具书啦.(暂时按随笔的更新时间排序) [Stack] c++ V.S. Java (2015.04.27) [Map]   c++ ...

  7. 沉淀再出发:java中的HashMap、ConcurrentHashMap和Hashtable的认识

    沉淀再出发:java中的HashMap.ConcurrentHashMap和Hashtable的认识 一.前言 很多知识在学习或者使用了之后总是会忘记的,但是如果把这些只是背后的原理理解了,并且记忆下 ...

  8. Java容器:HashTable, synchronizedMap与ConcurrentHashMap

    首先需要明确的是,不管使用那种Map,都不能保证公共混合调用的线程安全,只能保证单条操作的线程安全,在这一点上各Map不存在优劣. 前文中简单说过HashTable和synchronizedMap,其 ...

  9. Java中的ReentrantLock和synchronized两种锁定机制的对比

    问题:多个访问线程将需要写入到文件中的数据先保存到一个队列里面,然后由专门的 写出线程负责从队列中取出数据并写入到文件中. http://blog.csdn.net/top_code/article/ ...

随机推荐

  1. mysql之select(二)

    union 联合 作用: 把2次或多次查询结果合并起来. 要求:两次查询的列数一致.推荐:查询的每一列,相对应得列类型也一样. 可以来自于多张表.多次sql语句取出的列名可以不一致,此时,以第1个sq ...

  2. JDK环境变量解析

    设置环境变量 在java 中需要设置三个环境变量(1.5之后不用再设置classpath了,但个人强烈建议继续设置以保证向下兼用问题)JDK安装完成之后我们来设置环境变量:右击“我的电脑”,选择“属性 ...

  3. VBA高效删除不连续多行

    最近在搞VBA,在感叹Excel功能强大的同时,对于新接触的一门编程语言也很烦恼.很多基础的语法都要靠网上搜索.现总结一些学习到的心得. VBA高效删除不连续多行 在一个拥有几万条数据的Excel中, ...

  4. phpeclipse常用快捷键

    phpeclipse常用快捷键

  5. 跨浏览器兼容的HTML5视频音频播放器

    HTML5的video和audio标签是用来在网页中加入视频和音频的标签,在支持html5的浏览器中不需要预先加载Adobe Flash浏览器插件就能轻松快速的播放视频和音频文件.而html5medi ...

  6. Delphi对象变成Windows控件的前世今生(关键是设置句柄和回调函数)goodx

    ----------------------------------------------------------------------第一步,准备工作:预定义一个全局Win控件变量,以及一个精简 ...

  7. Dreamweaver修改页面编码

    想修改当前页面编码,可以选择菜单 :修改->页面属性->标题/编码 想设置新建页面默认编码,可以选择菜单: 编辑->首选参数->新建文档 的默认编码里面修改

  8. Linux命令行通配符

    如果我们想对一类文件批量操作,例如批量查看硬盘文件属性,那么正常命令是如下所示: [root@localhost Desktop]# ls /dev/sda1 [root@localhost Desk ...

  9. IE内存泄露与无法回收研究小结

    一.内存泄露    之前确实看了很多资料,但这位大哥的话可谓画龙点睛,不是奉承他,一下子就打通了我的任督二脉,请看: trarck 写道    IE下的内存泄露原因就是循环引用,IE的垃圾回收器不能很 ...

  10. istream, outstream使用及常见错误

    使用方法: 使用filebuf打开文件,并拷贝给istream/ostream. 如下面的例子中,实现读取并处理deseq文件夹下所有文件,输出到ostream fw. code: #include& ...