热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JavaConcurrentHashMap类解析

基于JDK7的ConcurrentHashMap源码1.存储结构staticfinalclassHashEntry{finalinthash;finalKkey;vo

基于JDK 7 的 ConcurrentHashMap 源码


1. 存储结构

static final class HashEntry<K,V> {final int hash;final K key;volatile V value;volatile HashEntry<K,V> next;
}

  • ConcurrentHashMap 和 HashMap 实现上类似&#xff0c;最主要的差别是 ConcurrentHashMap 采用了分段锁&#xff08;Segment&#xff09;&#xff0c;每个分段锁维护着几个桶&#xff08;HashEntry&#xff09;&#xff0c;多个线程可以同时访问不同分段锁上的桶&#xff0c;从而使其并发度更高&#xff08;并发度就是 Segment 的个数&#xff09;。
  • ConcurrentHashMap的桶结构和HashMap的主要区别是后两个元素声明为了 volatile 类型。
  • HashMap 支持 fail-fast 机制&#xff0c;而ConcurrentHashMap没有modCount字段&#xff0c;不支持fail-fast 机制。

段结构的定义(Segment)&#xff1a;

static final class Segment<K,V> extends ReentrantLock implements Serializable {private static final long serialVersionUID &#61; 2249069246763182397L;static final int MAX_SCAN_RETRIES &#61;Runtime.getRuntime().availableProcessors() > 1 ? 64 : 1;transient volatile HashEntry<K,V>[] table;transient int count;transient int modCount;transient int threshold;final float loadFactor;
}

final Segment<K,V>[] segments; // 一个ConcurrentHashMap有多个Segment

默认的并发级别为 16&#xff0c;也就是说默认创建 16 个 Segment。

static final int DEFAULT_CONCURRENCY_LEVEL &#61; 16;

如下图&#xff0c;第一层为Segment&#xff0c;第二层为HashEntry
在这里插入图片描述


2. size 操作


  • 每个 Segment 维护了一个 count 变量来统计该 Segment 中的键值对个数。 transient int count;
  • 在执行 size 操作时&#xff0c;需要遍历所有 Segment 然后把 count 累计起来。
  • ConcurrentHashMap 在执行 size 操作时先尝试不加锁&#xff0c;如果连续两次不加锁操作得到的结果一致&#xff0c;那么可以认为这个结果是正确的。
  • 尝试次数使用 RETRIES_BEFORE_LOCK 定义&#xff0c;该值为 2&#xff0c;retries 初始值为 -1&#xff0c;因此尝试次数为 3。
  • 如果尝试的次数超过 3 次&#xff0c;就需要对每个 Segment 加锁。

size() 操作源码&#xff1a;

/*** Number of unsynchronized retries in size and containsValue* methods before resorting to locking. This is used to avoid* unbounded retries if tables undergo continuous modification* which would make it impossible to obtain an accurate result.*/
static final int RETRIES_BEFORE_LOCK &#61; 2;public int size() {// Try a few times to get accurate count. On failure due to// continuous async changes in table, resort to locking.final Segment<K,V>[] segments &#61; this.segments;int size;boolean overflow; // true if size overflows 32 bitslong sum; // sum of modCountslong last &#61; 0L; // previous sumint retries &#61; -1; // first iteration isn&#39;t retrytry {for (;;) {// 超过尝试次数&#xff0c;则对每个 Segment 加锁if (retries&#43;&#43; &#61;&#61; RETRIES_BEFORE_LOCK) {for (int j &#61; 0; j < segments.length; &#43;&#43;j)ensureSegment(j).lock(); // force creation}sum &#61; 0L;size &#61; 0;overflow &#61; false;for (int j &#61; 0; j < segments.length; &#43;&#43;j) {Segment<K,V> seg &#61; segmentAt(segments, j);if (seg !&#61; null) {sum &#43;&#61; seg.modCount;int c &#61; seg.count;if (c < 0 || (size &#43;&#61; c) < 0)overflow &#61; true;}}// 连续两次得到的结果一致&#xff0c;则认为这个结果是正确的if (sum &#61;&#61; last)break;last &#61; sum;}} finally {if (retries > RETRIES_BEFORE_LOCK) {for (int j &#61; 0; j < segments.length; &#43;&#43;j)segmentAt(segments, j).unlock();}}return overflow ? Integer.MAX_VALUE : size;
}

3. JDK 1.8 的改动


  • JDK 1.7 使用分段锁机制来实现并发更新操作&#xff0c;核心类为 Segment&#xff0c;它继承自重入锁 ReentrantLock&#xff0c;并发度与 Segment 数量相等
  • JDK 1.8 使用了 CAS 操作来支持更高的并发度&#xff0c;在 CAS 操作失败时使用内置锁 synchronized
  • 并且 JDK 1.8 的实现也在链表过长时会转换为红黑树

本文参考自这里


推荐阅读
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 本文讨论了如何使用IF函数从基于有限输入列表的有限输出列表中获取输出,并提出了是否有更快/更有效的执行代码的方法。作者希望了解是否有办法缩短代码,并从自我开发的角度来看是否有更好的方法。提供的代码可以按原样工作,但作者想知道是否有更好的方法来执行这样的任务。 ... [详细]
  • 本文介绍了如何在Mac上使用Pillow库加载不同于默认字体和大小的字体,并提供了一个简单的示例代码。通过该示例,读者可以了解如何在Python中使用Pillow库来写入不同字体的文本。同时,本文也解决了在Mac上使用Pillow库加载字体时可能遇到的问题。读者可以根据本文提供的示例代码,轻松实现在Mac上使用Pillow库加载不同字体的功能。 ... [详细]
  • 重入锁(ReentrantLock)学习及实现原理
    本文介绍了重入锁(ReentrantLock)的学习及实现原理。在学习synchronized的基础上,重入锁提供了更多的灵活性和功能。文章详细介绍了重入锁的特性、使用方法和实现原理,并提供了类图和测试代码供读者参考。重入锁支持重入和公平与非公平两种实现方式,通过对比和分析,读者可以更好地理解和应用重入锁。 ... [详细]
  • Linux服务器密码过期策略、登录次数限制、私钥登录等配置方法
    本文介绍了在Linux服务器上进行密码过期策略、登录次数限制、私钥登录等配置的方法。通过修改配置文件中的参数,可以设置密码的有效期、最小间隔时间、最小长度,并在密码过期前进行提示。同时还介绍了如何进行公钥登录和修改默认账户用户名的操作。详细步骤和注意事项可参考本文内容。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • 本文介绍了一种轻巧方便的工具——集算器,通过使用集算器可以将文本日志变成结构化数据,然后可以使用SQL式查询。集算器利用集算语言的优点,将日志内容结构化为数据表结构,SPL支持直接对结构化的文件进行SQL查询,不再需要安装配置第三方数据库软件。本文还详细介绍了具体的实施过程。 ... [详细]
  • 如何使用Python从工程图图像中提取底部的方法?
    本文介绍了使用Python从工程图图像中提取底部的方法。首先将输入图片转换为灰度图像,并进行高斯模糊和阈值处理。然后通过填充潜在的轮廓以及使用轮廓逼近和矩形核进行过滤,去除非矩形轮廓。最后通过查找轮廓并使用轮廓近似、宽高比和轮廓区域进行过滤,隔离所需的底部轮廓,并使用Numpy切片提取底部模板部分。 ... [详细]
author-avatar
wugege
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有