代码编织梦想

Java 8中的ConcurrentHashMap是一个非常值得关注的数据结构,因为它放弃了分段锁的机制,而采用了全新的CAS和synchronized组合的方式来保证并发安全。我们一起来探讨一下ConcurrentHashMap为什么放弃了分段锁,并介绍其新的实现方式。
在这里插入图片描述

一、分段锁的局限性

在Java 5之前,Java的并发编程主要采用的是synchronized关键字来实现线程间的同步。这种方式虽然简单易用,但是它的效率非常低下,因为它只能保证在同一时间内只有一个线程能够进入同步块。因此,Java 5中引入了ReentrantLock、ReadWriteLock、Semaphore等更高效的同步工具。但是这些同步工具都是基于锁的机制,因此它们仍然存在一些局限性,例如:

  • 锁竞争:在多线程的情况下,由于每个线程需要获取锁才能访问共享资源,因此锁的竞争会导致性能的下降。
  • 锁粒度:锁的粒度过大或过小都会导致性能下降。如果锁的粒度过大,会导致竞争的线程过多,从而降低并发度;如果锁的粒度过小,会导致线程切换过于频繁,从而增加线程调度的开销。
  • 锁的重入:当一个线程已经获得了某个锁,并且在执行过程中又需要获取同一个锁时,就会出现锁的重入现象。虽然重入锁可以避免死锁的问题,但是它会增加锁的竞争和性能开销。

针对这些问题,Java 5中引入了ConcurrentHashMap这个并发集合类。ConcurrentHashMap通过将一个大的数据结构分解为多个小的数据结构,然后对每个小的数据结构加锁来实现线程安全。这种方式称为分段锁。
在这里插入图片描述
但是,分段锁的实现方式也存在一些问题。首先,由于每个小的数据结构都需要加锁,因此锁的竞争会增加。其次,由于每个小的数据结构的大小是固定的,因此在高并发的情况下,容易出现热点数据的问题,即某个小的数据结构被频繁地访问,从而导致该小的数据结构的锁竞争非常激烈。这会导致整个ConcurrentHashMap的性能下降。另外,分段锁的实现也存在一些复杂性,例如需要考虑锁的重入、死锁等问题。

二、ConcurrentHashMap的新实现方式

为了解决分段锁的局限性,Java 8中重新实现了ConcurrentHashMap,放弃了分段锁的机制,而采用了全新的CAS和synchronized组合的方式来保证并发安全。具体来说,Java 8中的ConcurrentHashMap采用了以下方式来实现线程安全:

  • 数组+链表+红黑树的数据结构:ConcurrentHashMap的内部数据结构由一个数组和链表(或红黑树)组成,其中数组的每个元素都指向一个链表(或红黑树),链表(或红黑树)存储了实际的键值对。
  • CAS(Compare and Swap)操作:在ConcurrentHashMap中,对于需要修改的操作(例如put、remove等),会采用CAS操作来实现。具体来说,CAS操作会先比较当前节点的值和期望值是否相等,如果相等,则将当前节点的值修改为新值,否则不进行任何操作。
  • synchronized块:为了保证数组的一致性,ConcurrentHashMap会在修改数组时使用synchronized块来保证同步性。具体来说,ConcurrentHashMap会将整个数组进行分段,每个段内部采用synchronized块来保证同步性,不同段之间可以并发地进行操作。

Java 8中的ConcurrentHashMap采用了这种全新的实现方式,既保证了并发安全,又避免了分段锁的局限性。具体来说,它具有以下优点:

  • 更高效的并发性能:由于不再需要对每个小的数据结构进行加锁,因此ConcurrentHashMap在高并发的情况下具有更高的性能。
  • 更少的复杂性:相比于分段锁,CAS和synchronized的组合方式更简单,实现也更加容易理解。
  • 更好的可伸缩性:由于不再需要对每个小的数据结构进行加锁,因此ConcurrentHashMap可以更好地适应不同的并发场景。
    在这里插入图片描述

三、总结

在多核处理器的背景下,Java 8中的ConcurrentHashMap采用了全新的实现方式,放弃了分段锁的机制,而采用了CAS和synchronized的组合方式来保证并发安全。这种实现方式具有更高的并发性能、更少的复杂性和更好的可伸缩性,因此成为了Java中并发编程的重要组件之一。同时,由于Java 8中的ConcurrentHashMap在内部实现上采用了数组+链表+红黑树的数据结构,也使得其具有较好的查找和遍历性能,可以适用于各种场景。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/CXikun/article/details/129836018

concurrenthashmap(jdk1.8)为什么要放弃segment_yamaxifeng_132的博客-爱代码爱编程_concurrenthashmap segment

今天看到一篇博客:jdk1.8的HashMap和ConcurrentHashMap,我想起了前段时间面试的一个问题:ConcurrentHashMap(JDK1.8)为什么要使用synchronized而不是可重入锁? 我想从下面几个角度讨论这个问题: 1. 锁的粒度 首先锁的粒度并没有变粗,甚至变得更细了。每当扩容一次,ConcurrentHashM

ConcurrentHashMap 在 Java7 和 8 有何不同?-爱代码爱编程

Java 7 版本的 ConcurrentHashMap Java 7 版本中的 ConcurrentHashMap 的结构示意图 从图中我们可以看出,在 ConcurrentHashMap 内部进行了 Segment 分段,Segment 继承了 ReentrantLock,可以理解为一把锁,各个 Segment 之间都是相互独立上锁的,互不影响

30-ConcurrentHashMap 在 Java7 和 8 有何不同?-爱代码爱编程

在 Java 8 中,对于 ConcurrentHashMap 这个常用的工具类进行了很大的升级,对比之前 Java 7 版本在诸多方面都进行了调整和变化。不过,在 Java 7 中的 Segment 的设计思想依然具有参考和学习的价值,所以在很多情况下面试官都会问你:ConcurrentHashMap 在 Java 7 和 Java 8 中的结构分别是什

java锁分段_java8的ConcurrentHashMap为何放弃分段锁-爱代码爱编程

jdk1.7分段锁的实现 和hashmap一样,在jdk1.7中ConcurrentHashMap的底层数据结构是数组加链表。和hashmap不同的是ConcurrentHashMap中存放的数据是一段段的,即由多个Segment(段)组成的。每个Segment中都有着类似于数组加链表的结构。 关于Segment ConcurrentHashMa

Java多线程学习二十一:ConcurrentHashMap 在 Java7 和 8 有何不同-爱代码爱编程

在 Java 8 中,对于 ConcurrentHashMap 这个常用的工具类进行了很大的升级,对比之前 Java 7 版本在诸多方面都进行了调整和变化。不过,在 Java 7 中的 Segment 的设计思想依然具有参考和学习的价值,所以在很多情况下面试官都会问你:ConcurrentHashMap 在 Java 7 和 Java 8 中的结构分别是什

【面试题】史上最全的大厂 Java 面试题合集,这些你都会吗?(火速收藏)-爱代码爱编程

以下为大家整理了史上最全的 Java 面试题,涉及大量 Java 面试知识点和相关试题。 JAVA基础 JAVA中的几种基本数据类型是什么,各自占用多少字节。 String类能被继承吗,为什么。 String,Stringbuffer,StringBuilder的区别。 ArrayList和LinkedList有什么区别。 讲讲类的实例化顺序,比如父类

java中常用的锁-爱代码爱编程

1、乐观锁 乐观锁是一种乐观思想,假定当前环境是读多写少,遇到并发写的概率比较低,读数据时认为别的线程不会正在进行修改(所以没有上锁)。写数据时,判断当前 与期望值是否相同,如果相同则进行更新(更新期间加锁,保证是原子性的)。 Java中的乐观锁: CAS,比较并替换,比较当前值(主内存中的值),与预期值(当前线程中的值,主内存中值的一份拷贝)是否一样,

Java的锁机制。乐观锁/悲观锁、公平锁/非公平锁、可重入锁、独占锁/共享锁、互斥锁/读写锁、分段锁、锁的状态(偏向锁、轻量级锁、重量级锁)、自旋锁。Java中8种锁机制,一步到位!-爱代码爱编程

Java锁的机制 一、公平锁/非公平锁 ​ 在ReentrantLock中包含了公平锁和非公平锁两种锁。 如果你用默认的构造函数来创建ReentrantLock对象,默认的锁策略就是非公平的。 1、公平锁 公平锁定义: ​ 多个线程按照申请锁的顺序去获得锁,线程会直接进入队列去排队,永远都是队列的第一位才能得到锁。 公平锁优缺点: 优点:所有

java8的ConcurrentHashMap为何放弃分段锁,为什么要使用CAS+Synchronized取代Segment+ReentrantLock-爱代码爱编程

原文地址:https://cloud.tencent.com/developer/article/1509556 今天突然被一个同事问到java8为何放弃分段锁,于是花了点时间针对这个问题进行了小小的总结。 jdk1.7分段锁的实现 和hashmap一样,在jdk1.7中ConcurrentHashMap的

《Java性能调优实战》笔记(一)Java编程性能调优、多线程性能优化-爱代码爱编程

文章目录 一、Java性能调优概述1.1 性能调优标准1.2 制定性能调优策略二、Java编程性能调优2.1 字符串2.2 正则表达式2.3 ArrayList和LinkedList的选择2.4 使用Stream提高遍历集合效率2.5 HashMap优化2.6 高并发下I/O优化2.7 避免使用Java序列化2.8 优化RPC网络通信2.9 NIO

JAVA-Hashtable,TreeMap,LinkedHashMap,ConcurrentHashMap,CAS模型-爱代码爱编程

hashtable也是一个散列表,存储内容是key-value映射,通过链地址法实现的哈希表 hashtable中不允许null值的key和value Hashtable继承的是字典类,而不是AbstractMap。是从JDK1.0开始提供的一个古老的类,目前已经不再建议使用了。 public class Hashtable<K,V>

JDK8的 CHM 为何放弃分段锁-爱代码爱编程

概述 我们知道, 在 Java 5 之后,JDK 引入了 java.util.concurrent 并发包 ,其中最常用的就是 ConcurrentHashMap 了, 它的原理是引用了内部的 Segment ( ReentrantLock )  分段锁,保证在操作不同段 map 的时候, 可以并发执行, 操作同段 map 的时候,进行锁的竞争和等待。从

一文彻底搞懂java中的各种锁_java廖廖的博客-爱代码爱编程

本篇主要内容如上 帮你总结好的锁: 乐观锁应用于CAS悲观锁应用于synchronized、vector、hashtable自旋锁应用于CAS可重入锁应用于synchronized、Reentrantlock、Lock读写锁应用于ReentrantReadWriteLock,CopyOnWriteArrayList、CopyOnWriteArray