Java - ConcurrentHashMap的原理

**这是JDK1.7的实现**

ConcurrentHashMap 类中包含两个静态内部类 HashEntry 和 Segment。

HashEntry 用来封装映射表的键 / 值对;Segment 用来充当锁的角色,每个 Segment 对象守护整个散列映射表的若干个桶。每个桶是由若干个 HashEntry 对象链接起来的链表。

一个 ConcurrentHashMap 实例中包含由若干个 Segment 对象组成的数组。HashEntry 用来封装散列映射表中的键值对。

在 HashEntry 类中,key,hash 和 next 域都被声明为 final 型,value 域被声明为 volatile 型。

Segment --->桶(bucket)--->HashEntry
static final class HashEntry<K,V> {
final K key; // 声明 key 为 final 型
final int hash; // 声明 hash 值为 final 型
volatile V value; // 声明 value 为 volatile 型
final HashEntry<K,V> next; // 声明 next 为 final 型 HashEntry(K key, int hash, HashEntry<K,V> next, V value) {
this.key = key;
this.hash = hash;
this.next = next;
this.value = value;
}
}

在ConcurrentHashMap 中,在散列时如果产生“碰撞”,将采用“分离链接法(链表法)”来处理“碰撞”:把“碰撞”的 HashEntry 对象链接成一个链表。由于 HashEntry 的 next 域为 final 型,所以新节点只能在链表的表头处插入。 下图是在一个空桶中依次插入 A,B,C 三个 HashEntry 对象后的结构图:

图1. 插入三个节点后桶的结构示意图:

注意:由于只能在表头插入,所以链表中节点的顺序和插入的顺序相反。

Segment 类继承于 ReentrantLock 类,从而使得 Segment 对象能充当锁的角色。每个 Segment 对象用来守护其(成员对象 table 中)包含的若干个桶。

Concurrenthashmap线程安全的,1.7是在jdk1.7中采用Segment + HashEntry的方式进行实现的,lock加在Segment上面。1.7size计算是先采用不加锁的方式,连续计算元素的个数,最多计算3次:

1、如果前后两次计算结果相同,则说明计算出来的元素个数是准确的;

2、如果前后两次计算结果都不同,则给每个Segment进行加锁,再计算一次元素的个数;

1.8中放弃了Segment臃肿的设计,取而代之的是采用Node + CAS + Synchronized来保证并发安全进行实现,1.8中使用一个volatile类型的变量baseCount记录元素的个数,当插入新数据或则删除数据时,会通过addCount()方法更新baseCount,通过累加baseCount和CounterCell数组中的数量,即可得到元素的总个数;

Java - ConcurrentHashMap的原理的更多相关文章

  1. Java ConcurrentHashMap

    通过分析Hashtable就知道,synchronized是针对整张Hash表的,即每次锁住整张表让线程独占, ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁分离技术. ...

  2. ConcurrentHashMap实现原理及源码分析

    ConcurrentHashMap实现原理 ConcurrentHashMap源码分析 总结 ConcurrentHashMap是Java并发包中提供的一个线程安全且高效的HashMap实现(若对Ha ...

  3. HashMap和ConcurrentHashMap实现原理及源码分析

    HashMap实现原理及源码分析 哈希表(hash table)也叫散列表,是一种非常重要的数据结构,应用场景及其丰富,许多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希表, ...

  4. ConcurrentHashMap实现原理

    ConcurrentHashMap是Java并发包中提供的一个线程安全且高效的HashMap实现(若对HashMap的实现原理还不甚了解,可参考我的另一篇文章HashMap实现原理及源码分析),Con ...

  5. Java LinkedHashMap工作原理及实现

    Java LinkedHashMap工作原理及实现 原文出处: Yikun 1. 概述 在理解了#7 介绍的HashMap后,我们来学习LinkedHashMap的工作原理及实现.首先还是类似的,我们 ...

  6. Java ConcurrentHashMap 源代码分析

    Java ConcurrentHashMap jdk1.8 之前用到过这个,但是一直不清楚原理,今天抽空看了一下代码 但是由于我一直在使用java8,试了半天,暂时还没复现过put死循环的bug 查了 ...

  7. Java面向切面原理与实践

    Java面向切面原理与实践 一. 面向切面编程是什么 首先用一句话概括:面向切面编程(AOP)就是对某些具有相似点的代码进行增强. 相似点可以是同一个包.使用相同的注解.public的方法.以Impl ...

  8. 嘿嘿,我就知道面试官接下来要问我 ConcurrentHashMap 底层原理了,看我怎么秀他

    前言 上篇文章介绍了 HashMap 源码后,在博客平台广受好评,让本来己经不打算更新这个系列的我,仿佛被打了一顿鸡血.真的,被读者认可的感觉,就是这么奇妙. 然后,有读者希望我能出一版 Concur ...

  9. Java ConcurrentHashMap Example and Iterator--转

    原文地址:http://www.journaldev.com/122/java-concurrenthashmap-example-iterator#comment-27448 Today we wi ...

随机推荐

  1. 关于webpack,你想知道的都在这;

    咱也标题党一回 哈哈哈 要使用webpack优化项目打包构建速度,首先得知道问题出在哪, 要知道问题出在哪,首先得知道webpack 打包的基本原理才能针对性的去做优化,下面首先了解webpack基本 ...

  2. LazyCaptcha自定义随机验证码和字体

    介绍 LazyCaptcha是仿EasyCaptcha和SimpleCaptcha,基于.Net Standard 2.1的图形验证码模块. 目前Gitee 52star, 如果对您有帮助,请不吝啬点 ...

  3. python---二叉树广度优先和深度优先遍历的实现

    class Node(object): """结点""" def __init__(self, data): self.data = dat ...

  4. Spring-JdbcTemplate(注入到spring容器)-02

    1.导入spring-jdbc和spring-tx坐标 <dependency> <groupId>junit</groupId> <artifactId&g ...

  5. Spring-aop注解开发(切点表达式的抽取)

    接上一篇aop注解快速开发 @Component @Aspect //标注当前aspect是切面类 public class MyAspect { @Before("Pointcut()&q ...

  6. [翻译] Cassandra 分布式结构化存储系统

    Cassandra 分布式结构化存储系统 摘要 Cassandra 是一个分布式存储系统,用于管理分布在许多商品服务器上的大量结构化数据,同时提供无单点故障(no single point of fa ...

  7. OpenHarmony 3.1 Beta版本关键特性解析——探秘隐式查询

    ​(以下内容来自开发者分享,不代表 OpenHarmony 项目群工作委员会观点)​ 徐浩 隐式查询是 OpenAtom OpenHarmony(以下简称"OpenHarmony" ...

  8. 记录,element ui的日期选择器只有第一次回显成功

    首先是这个 <el-date-picker v-model="value1" type="daterange" range-separator=" ...

  9. Caused by: com.sonatype.nexus.staging.client.StagingRuleFailuresException: Staging rules failure! 已解决!

    问题分析 由于项目中修改了一些代码,然后没有修改版本号,直接deploy代码到仓库,最终导致错误! 根据 https://central.sonatype.org/faq/can-i-change-a ...

  10. Java语言学习day14--7月19日

    ###10数组逆序功能实现 * A:案例代码 /* 数组的逆序: 数组中的元素,进行位置上的交换 逆序 不等于 反向遍历 就是数组中最远的两个索引,进行位置交换,实现数组的逆序 使用的是数组的指针思想 ...