【Java 基础】ConcurrentHashMap 底层原理

这篇具有很好参考价值的文章主要介绍了【Java 基础】ConcurrentHashMap 底层原理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

tip:作为程序员一定学习编程之道,一定要对代码的编写有追求,不能实现就完事了。我们应该让自己写的代码更加优雅,即使这会费时费力。

推荐:体系化学习Java(Java面试专题)

一、ConcurrentHashMap 底层原理

ConcurrentHashMap 是线程安全的哈希表,它是 Java 并发包中提供的一种高效的并发 Map 实现。ConcurrentHashMap 底层采用了分段锁的机制,不同的段(Segment)可以被不同的线程同时访问,从而提高了并发性能。

ConcurrentHashMap 采用了数组 + 链表 + 红黑树的数据结构来实现哈希表。数组的每个元素都是一个段(Segment),每个段都是一个独立的哈希表,包含了若干个键值对。每个段都有自己的锁,不同的段可以被不同的线程同时访问,从而提高了并发性能。

ConcurrentHashMap 的 put 操作和 get 操作都是非常高效的,因为它们都可以并发进行,不需要对整个哈希表加锁。在进行 put 操作时,先根据 key 的哈希值找到对应的段,然后对该段加锁,再在该段中进行插入操作;在进行 get 操作时,也是先根据 key 的哈希值找到对应的段,然后对该段加锁,再在该段中进行查找操作。这样就可以实现高并发的插入和查找操作。

ConcurrentHashMap 的扩容过程也是非常高效的。当某个段的元素个数超过了阈值时,就会触发扩容操作。在进行扩容操作时,只需要对该段加锁,不需要对整个哈希表加锁。同时,扩容时只需要将旧的元素重新分配到新的段中即可,不需要像 HashMap 那样重新计算所有元素的哈希值,因此扩容的效率更高。

总之,ConcurrentHashMap 底层采用了分段锁的机制,不同的段可以被不同的线程同时访问,从而提高了并发性能。同时,它采用了数组 + 链表 + 红黑树的数据结构来实现哈希表,具有高效的插入、查找、扩容等操作。

二、ConcurrentHashMap在java8和java7它的实现一样吗?

Java 8 中的 ConcurrentHashMap 引入了新的实现方式,称为基于 CAS(Compare and Swap)的实现,相比于 Java 7 中的基于分段锁的实现,具有更好的性能表现。此外,Java 8 中的 ConcurrentHashMap 还引入了新的方法,如 forEach、reduce、search 等,使得对 ConcurrentHashMap 的操作更加方便和高效。但是,Java 7 中的 ConcurrentHashMap 仍然可以使用,并且在某些场景下,其性能表现可能更好。

总结:
java 8:CAS + 分段锁
java 7:分段锁

三、Java 8 ConcurrentHashMap 主要实现方式

Java 8 中的 ConcurrentHashMap 实现采用了基于 CAS 的方式,其主要实现逻辑如下:

  1. ConcurrentHashMap 内部采用了一个数组来存储数据,每个数组元素称为一个“桶”,每个桶又是一个链表或红黑树,用于存储键值对。数组的大小会根据当前元素数量动态调整。

  2. ConcurrentHashMap 中的每个桶都有一个链表或红黑树,用于存储键值对。当链表长度超过阈值(默认为 8)时,会将链表转换为红黑树,以提高查找效率。

  3. ConcurrentHashMap 中的每个桶都有一个“基准计数”,用于记录该桶中键值对的数量。同时,每个线程都会维护一个“本地计数”,用于记录该线程向 ConcurrentHashMap 中插入的键值对数量。

  4. ConcurrentHashMap 中的 put 操作会先根据 key 的哈希值找到对应的桶,然后对该桶进行加锁(采用了一种乐观锁的方式,即不断尝试 CAS 操作),如果加锁成功,则进行插入操作。插入操作包括两个步骤:首先将键值对插入到桶中,然后将“基准计数”加 1。如果加锁失败,则重试插入操作。

  5. ConcurrentHashMap 中的 get 操作也会先根据 key 的哈希值找到对应的桶,然后对该桶进行加锁,如果加锁成功,则在该桶中查找对应的键值对。查找操作包括两个步骤:首先遍历链表或红黑树,查找对应的键值对;然后将“本地计数”加 1。如果加锁失败,则重试查找操作。

  6. ConcurrentHashMap 中的扩容操作会将所有的桶都进行扩容,扩容时会对每个桶进行加锁,不同的桶可以被不同的线程同时扩容。扩容操作包括两个步骤:首先将旧桶中的键值对重新分配到新桶中,然后将“基准计数”更新为新桶中键值对的数量。

总之,Java 8 中的 ConcurrentHashMap 实现采用了基于 CAS 的方式,同时引入了一些新的优化,如红黑树、基准计数、乐观锁等,使得其性能得到了很大的提升。

四、应用

package com.pany.camp.base;

import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentHashMapExample {

    public static void main(String[] args) {

        ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

        // 插入数据
        map.put("apple", 1);
        map.put("banana", 2);
        map.put("cherry", 3);

        // 获取数据
        System.out.println("apple: " + map.get("apple"));
        System.out.println("banana: " + map.get("banana"));
        System.out.println("cherry: " + map.get("cherry"));

        // 遍历数据
        map.forEach((key, value) -> System.out.println(key + ": " + value));
    }

}

我们创建了一个 ConcurrentHashMap 对象,并向其中插入了三个键值对。然后,我们分别使用 get 方法获取了这三个键对应的值,并使用 forEach 方法遍历了整个 ConcurrentHashMap。这个例子展示了 ConcurrentHashMap 的基本用法,包括插入、获取和遍历数据。由于 ConcurrentHashMap 是线程安全的,因此在多线程环境下使用时,不需要额外的同步措施,可以保证数据的一致性和正确性。文章来源地址https://www.toymoban.com/news/detail-676587.html

到了这里,关于【Java 基础】ConcurrentHashMap 底层原理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java ConcurrentHashMap 高并发安全实现原理解析,字节大牛耗时八个月又一力作

    //下一个哈希表 private transient volatile NodeK,V[] nextTable; //计数的基准值 private transient volatile long baseCount; //控制变量,不同场景有不同用途,参考下文 private transient volatile int sizeCtl; //并发搬运过程中CAS获取区段的下限值 private transient volatile int transferIndex; //计数cell初始化或者扩容

    2024年04月15日
    浏览(36)
  • 结合底层源码介绍ConcurrentHashMap如何保证线程安全,佬会爱上这篇文章嘛

    前言: 本篇文章主要讲解 结合底层源码介绍ConcurrentHashMap如何保证线程安全 的知识。该专栏比较适合刚入坑Java的小白以及准备秋招的大佬阅读。 如果文章有什么需要改进的地方欢迎大佬提出,对大佬有帮助希望可以支持下哦~ 小威在此先感谢各位小伙伴儿了😁 以下正文开

    2024年02月11日
    浏览(42)
  • ConcurrentHashMap原理详解(太细了)

    ConcurrentHashMap 和 HashMap 一样,是一个存放键值对的容器。使用 hash 算法来获取值的地址,因此时间复杂度是O(1)。查询非常快。 同时, ConcurrentHashMap 是线程安全的 HashMap 。专门用于多线程环境。 2.1 HashMap HashMap 是线程不安全的,因为 HashMap 中操作都没有加锁,因此在多线程环

    2024年02月03日
    浏览(71)
  • JavaEE 初阶篇-线程安全的集合类、多线程环境使用 ArrayList、队列、哈希表(HashMap 、ConCurrentHashMap 、HashTable 的区别)

    🔥博客主页: 【 小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍   文章目录         1.0 线程安全的集合类         1.2 线程安全的集合类 - Vector         1.3 线程安全的集合类 - Stack         1.4 线程安全的集合类 - HashTable         2.0 多线程环境使用 ArrayList        

    2024年04月25日
    浏览(51)
  • Java-集合-ConcurrentHashMap

    table:数组加volatile保证可见性和有序性 put():数组不存在,通过CAS创建;数组下标位置为空,通过CAS插入;数组下标位置不为空,给头节点加synchronized来插入链表或红黑树 ConcurrentHashMap是通过synchronized保证线程安全的吗? 不是,HashTable是单纯给方法加synchronized来保证单机线

    2024年02月10日
    浏览(74)
  • Java-多线程-深入理解ConcurrentHashMap

        ConcurrentHashMap(Concurrent: 并存的,同时发生的 ;)     ConcurrentHashMap是Java中的一个线程安全的哈希表实现,它可以在多线程环境下高效地进行并发操作。     HashMap线程不安全,在多线程操作下可能会导致数据错乱     使用HashMap和ConcurrentHashMap分别实

    2024年02月14日
    浏览(38)
  • Java进阶(ConcurrentHashMap)——面试时ConcurrentHashMap常见问题解读 & 结合源码分析 & 多线程CAS比较并交换 初识

    List、Set、HashMap作为Java中常用的集合,需要深入认识其原理和特性。 本篇博客介绍常见的关于Java中线程安全的ConcurrentHashMap集合的面试问题,结合源码分析题目背后的知识点。 关于List的博客文章如下: Java进阶(List)——面试时List常见问题解读 结合源码分析 关于的Set的博

    2024年02月06日
    浏览(60)
  • 【JAVA】concurrentHashMap和HashTable有什么区别

    🍎 个人博客: 个人主页 🏆 个人专栏: JAVA ⛳️   功不唐捐,玉汝于成 目录 前言 正文 同步性质: 性能: 允许空键值(Allow Nulls): 迭代器(Iterator): 继承关系: 结语  我的其他博客 在Java的集合框架中, ConcurrentHashMap 和 HashTable 都提供了线程安全的哈希表实现,用

    2024年01月16日
    浏览(53)
  • 【Java】HashMap、HashTable和ConcurrentHashMap的区别

    HashTable、HashMap和ConcurrentHashMap之间的区别主要体现在线程安全、继承关系与实现接口、对null值的处理、性能以及数据结构等几个方面。以下是对这三者之间区别的详细分析: 项目 HashMap HashTable ConcurrentHashMap null键 允许(仅能有一个) 不允许 允许(仅能有一个) null值 允许

    2024年04月25日
    浏览(57)
  • 【JAVA】Java8开始ConcurrentHashMap,为什么舍弃分段锁

    🍎 个人博客: 个人主页 🏆 个人专栏:      JAVA    ⛳️  功不唐捐,玉汝于成 目录 前言  正文 分段锁的好处: 结语 我的其他博客 前言  在Java 8中, ConcurrentHashMap 的实现经历了重大的改进,其中最引人注目的变化之一就是舍弃了传统的分段锁机制,转而采用了基于C

    2024年01月17日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包