今天我们要说的是关于集合的问题,实际上跟锁也有一定的关系,让我们来一起看看吧。

一、简介

1、是什么

ConcurrentHashMap是Java5中新增加的一个线程安全的Map集合,可以用来替代HashTable。对于ConcurrentHashMap是如何提高其效率的,可能大多人只是知道它使用了多个锁代替HashTable中的单个锁,也就是锁分离技术(Lock Stripping)。

2、为什么

为什么不用HashMap

hashmap本质数据加链表。根据key取得hash值,然后计算出数组下标,如果多个key对应到同一个下标,就用链表串起来,新插入的在前面。而且hashmap在单线程情况下效率较高。

但是在多线程环境下,使用Hashmap进行put操作会引起死循环,导致CPU利用率接近100%,所以在并发情况下不能使用HashMap。

为什么不用HashTable

HashTable容器使用synchronized来保证线程安全,但在线程竞争激烈的情况下HashTable的效率非常低下。因为当一个线程访问HashTable的同步方法时,其他线程访问HashTable的同步方法时,可能会进入阻塞或轮询状态。如线程1使用put进行添加元素,线程2不但不能使用put方法添加元素,并且也不能使用get方法来获取元素,所以竞争越激烈效率越低。

为什么要用ConcurrentHashMap

HashTable容器在竞争激烈的并发环境下表现出效率低下的原因,是因为所有访问HashTable的线程都必须竞争同一把锁,那假如容器里有多把锁,每一把锁用于锁容器其中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效的提高并发访问效率,这就是ConcurrentHashMap所使用的锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。

二、深入解析

1、结构图解析

ConcurrentHashMap和Hashtable主要区别就是围绕着锁的粒度以及如何锁,可以简单理解成把一个大的HashTable分解成多个,形成了锁分离。而Hashtable的实现方式是—锁整个hash表

从图中可以看到,ConcurrentHashMap内部分为很多个Segment,每一个Segment拥有一把锁,然后每个Segment(继承ReentrantLock)下面包含很多个HashEntry列表数组。对于一个key,需要经过三次(为什么要hash三次下文会详细讲解)hash操作,才能最终定位这个元素的位置,这三次hash分别为:

对于一个key,先进行一次hash操作,得到hash值h1,也即h1 = hash1(key);

将得到的h1的高几位进行第二次hash,得到hash值h2,也即h2 = hash2(h1高几位),通过h2能够确定该元素的放在哪个Segment;

将得到的h1进行第三次hash,得到hash值h3,也即h3 = hash3(h1),通过h3能够确定该元素放置在哪个HashEntry。

2、实现原理

ConcurrentHashMap把Map分成了N个Segment(默认16),其中Segment是线程同步的,相当于分成了N个Hashtable。当实现Put方法时,在key值经过正常的hash后,还要再经过一次segmentForHash算法,用来分配具体防盗哪个Segment。后来的线程如果经过计算也是放在这个Segment下,则需要先获取锁,如果计算得出应该放在其他的Segment,则正常执行,不会影响效率,以此实现线程安全。ConcurrentHashMap使用锁分离技术,只要多个修改操作不发生在同一个Segment上,它们就可以并发进行。

有些方法需要跨段,比如size()和containsValue(),需要锁定整个表而而不仅仅是某个段,这需要按顺序锁定所有段,操作完毕后,又按顺序释放所有段的锁。这里“按顺序”是很重要的,否则极有可能出现死锁,在ConcurrentHashMap内部,段数组是final的,并且其成员变量实际上也是final的,但是,仅仅是将数组声明为final的并不保证数组成员也是final的,这需要实现上的保证。这可以确保不会出现死锁,因为获得锁的顺序是固定的。

3、源码详解

这里不再细说,网上有很多。推荐Java并发包学习八]深度剖析ConcurrentHashMap

总结:

这个类其实在我们项目中的缓存使用到了,利用ConcurrentHashMap来存放一些常用的信息,由于是在并发的情况下使用,考虑到性能的问题,优先选用ConcurrentHashMap类。不过我建议大家还是要多看看源码,从中会受益很多。

concurrenthashmap是什么锁_多线程为什么要用ConcurrentHashMap相关推荐

  1. java runnable线程锁_多线程 java 同步 、锁 、 synchronized 、 Thread 、 Runnable

    线程 1 线程概述 1.1 什么是线程 v  线程是程序执行的一条路径, 一个进程中可以包含多条线程 v  一个应用程序可以理解成就是一个进程 v  多线程并发执行可以提高程序的效率, 可以同时完成多 ...

  2. java 多线程 张孝祥_多线程11_张孝祥 java5的线程锁技术

    本例子因为两个线程公用同线程中,使用同一个对象,实现了他们公用一把锁,实现了同一个方法的互斥. package locks; /** *会被打乱的效果 */ public class LockTest ...

  3. future.cancel不能关闭线程_多线程与高并发笔记

    1. 创建线程的四种方式 实现Runnable 重写run方法 继承Thread 重写run方法 线程池创建 Executors.newCachedThreadPool() 实现Callable接口 ...

  4. Java多线程系列(八):ConcurrentHashMap的实现原理(JDK1.7和JDK1.8)

    HashMap.CurrentHashMap 的实现原理基本都是BAT面试必考内容,阿里P8架构师谈:深入探讨HashMap的底层结构.原理.扩容机制深入谈过hashmap的实现原理以及在JDK 1. ...

  5. java 线程开销_多线程的线程开销

    多线程中两个必要的开销:线程的创建.上下文切换 创建线程: 创建线程使用是直接向系统申请资源的,对操作系统来说,创建一个线程的代价是十分昂贵的, 需要给它分配内存.列入调度,同时在线程切换的时候还要执 ...

  6. concurrenthashmap是什么锁_JDK1.8 util-concurrent-ConcurrentHashMap源码分析

    在介绍ConcurrentHashMap源码之前,很有必要复习下java并发编程中的一些基础知识,比如内存模型等.存储模型并发编程中的三个概念 1.原子性 2.可见性 3.重排序对HashMap在jd ...

  7. java+线程安全的hash,多线程下HashMap安全问题-ConcurrentHashMap解析

    Java1.5 引入了 java.util.concurrent 包,其中 Collection 类的实现允许在运行过程中修改集合对象.实际上, Java 的集合框架是[迭代器设计模式]的一个很好的实 ...

  8. 第四章Java核心类库_多线程

    第四章第五节Java核心类库_多线程 多线程 一.线程与进程 1.线程与进程 2.线程调度 二.同步与异步&并发与并行 1. 同步与异步 2. 并发与并行 三.继承Thread 1.代码块 2 ...

  9. 第十章_多线程(2)_线程池原子性并发工具类

    目录 一.线程池 1 - 线程状态 2 - 线程池 3 - Executors线程池 二.Volatile 三.原子性 四.并发工具类 1 - 并发工具类-Hashtable 2 - 并发工具类-Co ...

最新文章

  1. unity,standalone下自定义分辨率不起作用的解法
  2. Angular中提示:Can't bind to 'ngModel' since it isn't a known property of 'input'
  3. HTML表格,table,thead,tbody,tfoot,th,tr,td,的属性以及跨行,跨列
  4. Taro+react开发(51) 数组对象和数组得处理
  5. LeetCode 1005. K 次取反后最大化的数组和
  6. 2、SQL UNION 和 UNION ALL 操作符
  7. 【LeetCode】剑指 Offer 60. n个骰子的点数
  8. MoneyRunner API汇总
  9. ipcfg报错_CentOS服务器安装Anaconda
  10. Android 加载网络图片
  11. json在线解析工具
  12. LabVIEW强制重新安装无法运行或损坏的NI软件
  13. 监控--CactiEZ使用
  14. 原生javascript分页 html分页与ajax数据请求结合使用 前端js分页
  15. 图片太大了怎么改小kb?
  16. 【转】区块链经济学:制度加密经济学入门指南
  17. 重启Oracle数据库的操作步骤
  18. Markdown编辑器 公式指导手册
  19. 图像语义分割——利用DeeplabV3+预测单张照片
  20. Win10下安装必应输入法能导致Alt+Tab切换页面时不能置于最前

热门文章

  1. Hadoop 统计单词字数的例子
  2. ASP操作MSQL类
  3. Google Gears 体验(2):本机 web 服务器
  4. access port 与portfast之间的关系
  5. 让时间倒流的保存点:用Apache Flink的保存点技术重新处理数据流
  6. SQL JOIN的用法
  7. kingshard--一个支持sharding的MySQL Proxy项目
  8. android NDK 在Ubuntu10.04开发环境的搭建
  9. javascript对象操作总结
  10. C++ Vector学习笔记