Java并发体系--ConcurrentHashMap

ConcurrentHashMap     

   ConcurrentHashMap是Java中的一个线程安全的哈希表实现类。它继承自HashMap,具有与HashMap相似的功能,但在并发的场景下提供了更好的性能。

   ConcurrentHashMap采用了锁分段技术来实现线程安全。它将哈希表分成多个段(Segment),每个段管理一部分的键值对。不同的线程可以同时访问不同的段,从而提高并发性能。

   在ConcurrentHashMap中,每个段内部维护一个HashEntry数组,通过哈希值将键值对分别存储到不同的数组位置上。当多个线程同时访问不同的段时,它们可以同时进行读取操作,而对于同一段的写操作会进行同步处理。

    ConcurrentHashMap还提供了一些其他的线程安全的操作,例如原子性的putIfAbsent、replace和remove等方法,以及批量操作的forEach和replaceAll方法。

CAS + Synchronized

        ConcurrentHashMap是一个线程安全的哈希表,它使用了一种结合了CAS(Compare and Swap)和Synchronized(同步)的锁机制来保证线程安全性。

      在ConcurrentHashMap中,CAS用于保证对于哈希表的读写操作的原子性。CAS是一种乐观锁机制,它通过比较内存中的值与期望值是否相等来确定该值是否被修改过。如果相等,则将新值写入内存,否则重新尝试。这样可以避免了传统的锁机制所带来的性能损失。

    在ConcurrentHashMap中,Synchronized用于保证对于哈希表的结构修改操作的原子性。当需要对哈希表进行插入、删除、更新等操作时,使用Synchronized来保证同一时间只有一个线程能够修改哈希表的结构,从而避免了并发修改导致的数据不一致性。

     ConcurrentHashMap使用CAS和Synchronized相结合的方式来保证线程安全。CAS保证了对于哈希表的读写操作的原子性,而Synchronized保证了对于哈希表的结构修改操作的原子性。这种结合方式既保证了线程安全,又尽可能地提高了并发性能。

重要内部类

      ConcurrentHashMap 的重要内部类主要包括以下几种:

  1. Segment:Segment 是 ConcurrentHashMap 的内部类,它本质上是一个 HashEntry 数组,用于存储键值对。ConcurrentHashMap 使用多个 Segment 来分割整个哈希表,每个 Segment 管理一部分键值对,不同的线程可以同时访问不同的 Segment,从而实现并发访问。

  2. HashEntry:HashEntry 是 ConcurrentHashMap 内部用于存储键值对的节点。每个 HashEntry 包含一个 key 和一个 value,它们通过链表的方式连接在一起形成一个桶。当多个键值对的 hash 值相同时,它们会存储在同一个桶中,通过链表来解决哈希冲突。

  3. HashIterator:HashIterator 是 ConcurrentHashMap 的内部迭代器,用于遍历 ConcurrentHashMap 中的键值对。它继承了抽象类 ConcurrentHashMap.Traverser,并实现了 Iterator 接口。HashIterator 通过遍历每个 Segment 中的 HashEntry 数组来实现对 ConcurrentHashMap 的遍历。

  4. KeySetView:KeySetView 是 ConcurrentHashMap 的内部类,它实现了 Set 接口,用于获取 ConcurrentHashMap 的键的视图。KeySetView 通过内部类方式实现,包含了一个 ConcurrentHashMap 和一个共享的默认值。当对 KeySetView 进行操作时,会影响到 ConcurrentHashMap 中的键。

  5. ValuesView:ValuesView 是 ConcurrentHashMap 的内部类,它实现了 Collection 接口,用于获取 ConcurrentHashMap 的值的视图。ValuesView 通过内部类方式实现,包含了一个 ConcurrentHashMap。当对 ValuesView 进行操作时,会影响到 ConcurrentHashMap 中的值。

  6. EntrySetView:EntrySetView 是 ConcurrentHashMap 的内部类,它实现了 Set 接口,用于获取 ConcurrentHashMap 的键值对的视图。EntrySetView 通过内部类方式实现,包含了一个 ConcurrentHashMap。当对 EntrySetView 进行操作时,会影响到 ConcurrentHashMap 中的键值对。

重要操作

      ConcurrentHashMap的重要操作包括:

  1. put(key, value): 将指定的键值对添加到ConcurrentHashMap中。
  2. get(key): 获取指定键的值。
  3. remove(key): 删除指定键的值。
  4. containsKey(key): 检查ConcurrentHashMap中是否包含指定的键。
  5. containsValue(value): 检查ConcurrentHashMap中是否包含指定的值。
  6. isEmpty(): 检查ConcurrentHashMap是否为空。
  7. size(): 返回ConcurrentHashMap中的键值对数量。
  8. keySet(): 返回ConcurrentHashMap中所有键的集合。
  9. values(): 返回ConcurrentHashMap中所有值的集合。
  10. entrySet(): 返回ConcurrentHashMap中所有键值对的集合。
  11. putIfAbsent(key, value): 在ConcurrentHashMap中仅在指定的键不存在时才添加指定的键值对。
  12. replace(key, oldValue, newValue): 替换ConcurrentHashMap中指定键的值,仅当当前值与旧值相等时才进行替换。
  13. replace(key, value): 替换ConcurrentHashMap中指定键的值。
  14. clear(): 清空ConcurrentHashMap中的所有键值对。

1.8 与 1.7的区别     

    在Java 1.7中,ConcurrentHashMap的内部实现使用了分段锁(Segment Locks)来实现并发操作。每个段(Segment)都可以看作是一个小的HashMap,它们仅控制特定区域的数据。这种设计可以降低并发操作之间的冲突,提高并发性能。

    然而,在Java 1.8中,ConcurrentHashMap的内部实现变得更加简单和高效。在1.8中,ConcurrentHashMap使用了一种称为“基于CAS的非阻塞算法”的实现方式。这种实现方式不再使用分段锁,而是使用了一种称为“CAS(Compare and Swap)”的机制来实现并发操作。

    CAS是一种乐观锁的机制,它允许多个线程同时进行自由读写操作。当线程尝试进行写操作时,CAS会先进行比较当前值和期望值是否相等,如果相等则进行更新操作,否则重新尝试。这种方式避免了锁的使用,减少了线程之间的竞争,从而提高了并发性能。

    Java 1.8中的ConcurrentHashMap使用了一种基于CAS的非阻塞算法,相比于1.7中的分段锁机制,它的内部实现更加高效和简单。这使得1.8中的ConcurrentHashMap在并发操作下具有更好的性能表现。

 实例  

     ConcurrentHashMap 是线程安全的哈希表实现,它支持高并发环境下的并发操作。下面是 ConcurrentHashMap 的 代码示例:

import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentHashMapExample {

    public static void main(String[] args) {
        // 创建一个 ConcurrentHashMap 对象
        ConcurrentHashMap<String, Integer> concurrentHashMap = new ConcurrentHashMap<>();

        // 在多线程环境下向 ConcurrentHashMap 中添加元素
        Thread thread1 = new Thread(() -> {
            concurrentHashMap.put("A", 1);
            concurrentHashMap.put("B", 2);
            concurrentHashMap.put("C", 3);
        });

        Thread thread2 = new Thread(() -> {
            concurrentHashMap.put("D", 4);
            concurrentHashMap.put("E", 5);
            concurrentHashMap.put("F", 6);
        });

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 输出 ConcurrentHashMap 的内容
        concurrentHashMap.forEach((key, value) -> System.out.println(key + ": " + value));
    }

}

   上述示例中,首先创建了一个 ConcurrentHashMap 对象 concurrentHashMap

    然后通过两个线程同时向 concurrentHashMap 中添加元素。由于 ConcurrentHashMap 的线程安全性,不会出现并发冲突的情况。

    最后,使用 forEach 方法遍历 ConcurrentHashMap 的内容,并打印出每个键值对。

    ConcurrentHashMap 内部使用了分段锁机制,将整个哈希表分成多个小的哈希表,每个小的哈希表对应一个锁。这样,在多线程环境下,如果多个线程分别操作不同的小哈希表,就可以同时进行,提高了并发性能。

    需要注意的是,虽然 ConcurrentHashMap 是线程安全的,但并不意味着它可以代替所有的同步容器。在一些特定的场景下,可能需要使用其他的同步容器或并发集合类来满足具体的需求。

总结

     ConcurrentHashMap是Java中线程安全的哈希表实现。它与HashMap相比,能够在多线程环境下提供更好的性能和并发访问的能力。

以下是ConcurrentHashMap的一些特点和总结:

  1. 线程安全:ConcurrentHashMap使用了锁分段技术,将整个数据结构分成多个段(Segment),每个段都有自己的锁。这意味着多个线程可以同时访问不同的段,从而提高了并发性能。

  2. 并发度高:ConcurrentHashMap的并发度是通过扩展段(Segment)来实现的。默认情况下,ConcurrentHashMap的并发度是16,即有16个段。

  3. put操作是原子性的:ConcurrentHashMap的put操作是原子性的,不需要额外的同步措施。这意味着多个线程可以同时进行put操作,而不会出现数据不一致的问题。

  4. 读操作不需要加锁:由于ConcurrentHashMap使用了锁分段技术,所以读操作不需要加锁。这使得ConcurrentHashMap在读多写少的场景下表现良好。

  5. 适用于高并发场景:ConcurrentHashMap适用于高并发场景,特别是读多写少的场景。它可以提供更好的性能和并发访问能力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/560401.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

前后端跨域请求代码实战(vue3.4+springboot2.7.18)

前端代码 v3.4.21&#xff08;前端不是主业&#xff0c;所以就贴一贴代码&#xff0c;有疑问评论区见&#xff09;后端代码&#xff0c;springboot 2.7.18&#xff08;后端&#xff09; 文章内容&#xff1a; 一&#xff0c;后端代码 二&#xff0c;前端代码 三&#xff0c;后…

安全开发实战(1)--Cdn

目录 安全开发专栏 CDN介绍 1.信息收集阶段 1.1判断CDN是否存在 1.1.1, One 1.1.2,Two(改进) 1.1.3,进行整合 增加输入功能 1.1.4 批量读取监测存储(进行测试) 问题1: 问题2: 解决方案: 1.1.4 基本编写完成 命令框中: cdn存在.txt 总结 这里我是根据整个渗透测…

个人网页地址发布页面源码

源码介绍 个人网页地址发布页面源码&#xff0c;源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面 效果预览 源码下载 个人网页地址发布页面源码

利用搞笑电影,引爆中年圈,日入2000+,短视频最新变现玩法,适合0基础小白

大家好&#xff0c;今天要分享的项目是“通过搞笑电影吸引中年群体&#xff0c;实现日收入2000的短视频变现新策略&#xff0c;适合零基础新手”。该项目着眼于利用搞笑电影内容来吸引中年观众&#xff0c;这是一个相对未被充分开发的市场领域&#xff0c;竞争较少。与其他热门…

香港服务器_免备案服务器有哪些正规的?企业、建站方向

香港服务器&#xff0c;是最受欢迎的外贸、企业建站服务器&#xff0c;在个人建站领域&#xff0c;香港服务器、香港虚拟主机都是首选的网站服务器托管方案&#xff0c;不仅其具备免备案的特点&#xff0c;而且国内外地区访问速度都很快。那么&#xff0c;现今2024年个人和企业…

企业监管工具:为何如此重要?

随着通信技术的发展&#xff0c;员工使用微信等即时通讯工具来进行工作沟通已经成为了常态。为了帮助企业有效地监管员工的工作微信使用情况&#xff0c;微信管理系统应运而生。 下面就一起来看看&#xff0c;它都有哪些功能吧&#xff01; 1、历史消息&#xff1a;洞察员工聊…

力扣---从前序与中序遍历序列构造二叉树

给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一棵树的中序遍历&#xff0c;请构造二叉树并返回其根节点。 示例 1: 输入: preorder [3,9,20,15,7], inorder [9,3,15,20,7] 输出: [3,9,20,null,null,15,7]示…

IO——进程间通讯 IPC

1. 进程间通信方式 (1) 早期进程间通信&#xff1a; 无名管道(pipe)、有名管道(fifo)、信号(signal) (2) system V IPC&#xff1a; 共享内存(shared memory)、消息队列(message queue)、信号灯集(semaphore set) (3) BSD&#xff1a; 套接字(socket) 2. 无名管道 2.1特点 …

泛微E9开发 快速隐藏明细表列

快速隐藏明细表列 1、隐藏列方法&#xff08;不作用&#xff0c;一直隐藏&#xff09; 在实际运用中&#xff0c;用户不需要但是需要间接使用的列&#xff0c;我们可以通过右击该列-【列自定义属性】-在“列自定义属性”菜单中启用“隐藏列”功能。 根据该方法设置的前端页…

基于Springboot的社区疫情返乡管控系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的社区疫情返乡管控系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系…

OpenHarmony 上传和下载(API 10)教程~

介绍 本示例使用ohos.request接口创建上传和下载任务&#xff0c;实现上传、下载功能&#xff0c;hfs作为服务器&#xff0c;实现了文件的上传和下载和任务的查询功能。 效果预览 使用说明 1.本示例功能需要先配置服务器环境后使用&#xff0c;具体配置见上传下载服务配置。…

中颖51芯片学习7. printf重定向到串口与自定义日志输出函数

中颖51芯片学习7. printf重定向到串口与自定义日志输出函数 一、 printf 重定向1. 概念2. 实现方式3. C51 中printf数值格式化 二、日志函数1. 实现方案分析2. 代码&#xff08;1&#xff09;log_utils.h&#xff08;2&#xff09;main.c 3. 通过预定义宏实现日志分级输出&…

汇编语言88888

汇编语言安装指南 第一步&#xff1a;在github上下载汇编语言的安装包 网址&#xff1a;GitHub - HaiPenglai/bilibili_assembly: B站-汇编语言-pdf、代码、环境等资料B站-汇编语言-pdf、代码、环境等资料. Contribute to HaiPenglai/bilibili_assembly development by creat…

Flyweight 享元

意图 运用共享技术有效地支持大量细粒度的对象。 结构 其中 Flyweight描述一个接口&#xff0c;通过这个接口Flyweight可以接受并作用于外部状态。ConcreteFlyweight实现Flyweight接口&#xff0c;并作为内部状态&#xff08;如果有&#xff09;增加存储空间。ConcreteFlywe…

数字阅览室解决方案

一、方案概述 “数字阅览室”概念一经提出&#xff0c;就得到了广泛的关注&#xff0c;纷纷组织力量进行探讨、研究和开发&#xff0c;进行各种模型的试验。随着数字地球概念、技术、应用领域的发展&#xff0c;数字阅览室已成为数字地球家庭的成员&#xff0c;为信息高速公路…

vue3:树的默认勾选和全选、取消全选

实现的功能&#xff0c;上面有个选择框&#xff0c;当选中全部时&#xff0c;下方树被全选 代码&#xff1a; <template><div><el-select v-model"selectAll" style"margin-bottom: 10px;" change"handleSelectAllChange">&…

运行transformers报错check_min_version(“4.40.0.dev0“)

在huggingface &#xff08;transformers项目地址&#xff09;下载transformers的项目 并 python /transformers/examples/pytorch/language-modeling/run_clm.py 时报错 报错如下&#xff1a; 安装的 transformers 版本不对&#xff0c;这里安装了 4.39.3&#xff0c;实际想…

网站备案期间怎么关闭首页显示无法访问-文章及其它页面正常访问

自从做了开发者之后才发现每个人博主的需求都是不同的&#xff0c;的的确确颠覆了我的观点&#xff0c;无论是页面布局还是SEO相关的设置&#xff0c;可能是因为站点属性不同所以需求不同&#xff0c;慢慢的就会在主题加入一些自定接口来满足不同人的需求&#xff0c;有人需要P…

双链表的实现

我们知道链表其实有很多种&#xff0c;什么带头&#xff0c;什么双向啊&#xff0c;我们今天来介绍双向带头循环链表&#xff0c;了解了这个其他种类的链表就很简单了。冲冲冲&#xff01;&#xff01;&#xff01; 链表的简单分类 链表有很多种&#xff0c;什么带头循环链表&…

【c基础】文件操作

1.fopen和fclose函数 函数原型 FILE *fopen(const char *path, const char *mode); 参数解释&#xff1a; 返回值&#xff1a;fopen打开成功&#xff0c;则返回有效file的有效地址&#xff0c;失败返回NULL。path是文件路径&#xff0c;可以相对路径&#xff0c;可以绝对路径…
最新文章