`

ConcurrentHashMap 理解

    博客分类:
  • java
阅读更多

ConcurrentHashMap是Java 5中支持高并发、高吞吐量的线程安全HashMap实现。

ConcurrentHashMap 类中包含两个静态内部类 HashEntry 和 Segment。HashEntry 用来封装映射表的键 / 值对;Segment 用来充当锁的角色,每个 Segment 对象守护整个散列映射表的若干个桶。每个桶是由若干个 HashEntry 对象链接起来的链表。一个 ConcurrentHashMap 实例中包含由若干个 Segment 对象组成的数组。

HashEntry 类

HashEntry 用来封装散列映射表中的键值对。在 HashEntry 类中,key,hash 和 next 域都被声明为 final 型,value 域被声明为 volatile 型。

在 ConcurrentHashMap 中,在散列时如果产生“碰撞”,将采用“分离链接法”来处理“碰撞”:把“碰撞”的 HashEntry 对象链接成一个链表。由于 HashEntry 的 next 域为 final 型,所以新节点只能在链表的表头处插入。注意:由于只能在表头插入,所以链表中节点的顺序和插入的顺序相反。

Segment 类

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

table 是一个由 HashEntry 对象组成的数组。table 数组的每一个数组成员就是散列映射表的一个桶。

count 变量是一个计数器,它表示每个 Segment 对象管理的 table 数组(若干个 HashEntry 组成的链表)包含的 HashEntry 对象的个数。每一个 Segment 对象都有一个 count 对象来表示本 Segment 中包含的 HashEntry 对象的总数。注意,之所以在每个 Segment 对象中包含一个计数器,而不是在 ConcurrentHashMap 中使用全局的计数器,是为了避免出现“热点域”而影响 ConcurrentHashMap 的并发性。

注意:这里的加锁操作是针对(键的 hash 值对应的)某个具体的 Segment,锁定的是该 Segment 而不是整个 ConcurrentHashMap。因为插入键 / 值对操作只是在这个 Segment 包含的某个桶中完成,不需要锁定整个ConcurrentHashMap。此时,其他写线程对另外 15 个Segment 的加锁并不会因为当前线程对这个 Segment 的加锁而阻塞。同时,所有读线程几乎不会因本线程的加锁而阻塞(除非读线程刚好读到这个 Segment 中某个 HashEntry 的 value 域的值为 null,此时需要加锁后重新读取该值)。

相比较于 HashTable 和由同步包装器包装的 HashMap每次只能有一个线程执行读或写操作,ConcurrentHashMap 在并发访问性能上有了质的提高。在理想状态下,ConcurrentHashMap 可以支持 16 个线程执行并发写操作(如果并发级别设置为 16),及任意数量线程的读操作。

在实际的应用中,散列表一般的应用场景是:除了少数插入操作和删除操作外,绝大多数都是读取操作,而且读操作在大多数时候都是成功的。正是基于这个前提,ConcurrentHashMap 针对读操作做了大量的优化。通过 HashEntry 对象的不变性和用 volatile 型变量协调线程间的内存可见性,使得 大多数时候,读操作不需要加锁就可以正确获得值。这个特性使得 ConcurrentHashMap 的并发性能在分离锁的基础上又有了近一步的提高。

总结

ConcurrentHashMap 是一个并发散列映射表的实现,它允许完全并发的读取,并且支持给定数量的并发更新。相比于 HashTable 和用同步包装器包装的 HashMap(Collections.synchronizedMap(new HashMap())),ConcurrentHashMap 拥有更高的并发性。在 HashTable 和由同步包装器包装的 HashMap 中,使用一个全局的锁来同步不同线程间的并发访问。同一时间点,只能有一个线程持有锁,也就是说在同一时间点,只能有一个线程能访问容器。这虽然保证多线程间的安全并发访问,但同时也导致对容器的访问变成串行化的了。

在使用锁来协调多线程间并发访问的模式下,减小对锁的竞争可以有效提高并发性。有两种方式可以减小对锁的竞争:

  1. 减小请求 同一个锁的 频率。
  2. 减少持有锁的 时间。

ConcurrentHashMap 的高并发性主要来自于三个方面:

  1. 用分离锁实现多个线程间的更深层次的共享访问。
  2. 用 HashEntery 对象的不变性来降低执行读操作的线程在遍历链表期间对加锁的需求。
  3. 通过对同一个 Volatile 变量的写 / 读访问,协调不同线程间读 / 写操作的内存可见性。

使用分离锁,减小了请求 同一个锁的频率。

通过 HashEntery 对象的不变性及对同一个 Volatile 变量的读 / 写来协调内存可见性,使得 读操作大多数时候不需要加锁就能成功获取到需要的值。由于散列映射表在实际应用中大多数操作都是成功的 读操作,所以 2 和 3 既可以减少请求同一个锁的频率,也可以有效减少持有锁的时间。

通过减小请求同一个锁的频率和尽量减少持有锁的时间 ,使得 ConcurrentHashMap 的并发性相对于 HashTable 和用同步包装器包装的 HashMap有了质的提高。

分享到:
评论

相关推荐

    JDK1.8中ConcurrentHashMap中computeIfAbsent死循环bug.docx

    我们首先来理解`computeIfAbsent`方法的基本概念,然后再深入分析这个问题的成因及解决方案。 `computeIfAbsent`是JDK 1.8中新增的一个功能强大的方法,它的作用是在给定的键不存在于映射中时,通过提供的函数来...

    java7-8中的 HashMap和ConcurrentHashMap全解析

    在Java编程语言中,`HashMap`和`ConcurrentHashMap`...理解它们的工作原理和优缺点,能够帮助开发者更有效地使用这些数据结构,优化代码性能。对于Java开发者来说,深入掌握这两个类的使用,是提高编程技能的重要环节。

    高薪程序员面试题精讲系列49之说说ConcurrentHashMap#put方法的源码及数。。。.pdf,这是一份不错的文件

    本文将对ConcurrentHashMap#put方法的源码进行详细分析,从而帮助读者更好地理解ConcurrentHashMap的工作机理。 一、ConcurrentHashMap的底层原理 ConcurrentHashMap是基于哈希表实现的,可以存储大量的数据。其...

    java7-8中的 HashMap和ConcurrentHashMap全解析.pdf

    本篇文章将深入解析这两种数据结构的内部实现,帮助读者理解它们的工作原理。 HashMap是Java中最常用的哈希表实现,它通过哈希函数快速定位键值对,并通过链表解决哈希冲突。在Java 7中,HashMap的内部结构主要由一...

    ConcurrentHashMap的实现原理(JDK1.7和JDK1.8).pdf

    在理解`ConcurrentHashMap`的实现原理之前,我们先来看看哈希表的基本概念。 哈希表是一种键值对存储的数据结构,通过键(key)进行索引,可以高效地查找、插入和删除数据。如果键是整数,我们可以直接用它作为数组...

    71-ConcurrentHashMap笔记1

    《并发编程:深入理解JDK1.8 ConcurrentHashMap》 ConcurrentHashMap是Java并发编程中不可或缺的一个数据结构,它在JDK1.8中进行了重大的优化,极大地提升了并发性能。相较于早期版本,JDK1.8的ConcurrentHashMap...

    Java中的ConcurrentHashMap:线程安全的哈希表实现与代码示例

    最后,我们对比了 ConcurrentHashMap 与其他常见并发数据结构的优缺点,帮助读者更好地理解其适用场景和优势。 在实际应用中,我们需要根据具体的场景和需求来选择合适的数据结构。如果需要高并发访问和更新,那么 ...

    ConcurrentHashMap源码分析

    ConcurrentHashMap是Java中用于支持高并发访问的哈希表实现,它是Java并...通过阅读和理解ConcurrentHashMap的源码,我们可以更好地掌握并发编程的技术细节,并在实际工作中有效地应用这些知识来解决并发环境下的问题。

    一文让你彻底理解JavaHashMap和ConcurrentHashMap

    本篇主要想讨论ConcurrentHashMap这样一个并发容器,在正式开始之前我觉得有必要谈谈HashMap,没有它就不会有后面的ConcurrentHashMap。众所周知HashMap底层是基于数组+链表组成的,不过在jdk1.7和1.8中具体实现稍有...

    24 经典并发容器,多线程面试必备。—深入解析ConcurrentHashMap.pdf

    【源码分析】深入理解`ConcurrentHashMap`的工作原理,需要查看其源码,特别是`put`、`get`、`resize`等关键操作,以及在不同版本中的变化,例如Java 8引入的红黑树优化。 总结,`ConcurrentHashMap`是Java并发编程...

    ConcurrentHashMap底层实现机制的分析1

    了解 ConcurrentHashMap 的实现机制有助于我们更好地理解 Java 并发编程的原理和技术。 一、Java 内存模型 Java 内存模型是 Java 语言的基础,它规定了线程对内存的访问如何排序以及何时可以确保它们对线程是可见...

    JDK1.8 ConcurrentHashMap的一点理解

    只是都是相通的,当我们了解了ConcurrentHashMap的实现原理以及各个方法的实现机制,我们对于其他的hash类型实现也能快速的理解,今天我们就来通过源码来一点一点的分析下ConcurrentHashMap的实现。 首先我们来看...

    HashMap,HashTable,ConcurrentHashMap之关联.docx

    HashMap,HashTable,ConcurrentHashMap 之关联 HashMap、HashTable、ConcurrentHashMap 是 Java 集合类中的重点,以下...理解它们的内部结构和特点是非常重要的,为此,我们需要不断学习和实践,掌握它们的原理和应用。

    第10讲 如何保证集合是线程安全的 ConcurrentHashMap如何实现高效地线程安全1

    在面试或实际开发中,理解ConcurrentHashMap的工作原理是非常重要的。面试官可能会询问关于它的内部实现,如Segment和HashEntry的结构,以及如何通过CAS操作避免锁竞争。此外,还需要了解从Java 5到Java 8,...

    25 经典并发容器,多线程面试必备—深入解析ConcurrentHashMap下.pdf

    在Java并发编程中,`ConcurrentHashMap`是一个重要的并发容器,它是`HashMap`的一个线程安全版本,适用于多线程环境。本节我们将深入解析`...理解和掌握其工作原理对于进行多线程面试和日常开发工作都至关重要。

    Java 多线程与并发(13-26)-JUC集合- ConcurrentHashMap详解.pdf

    【Java 多线程与并发】并发集合类`ConcurrentHashMap`是Java程序设计中一个重要的工具,尤其在高并发场景下,它提供了高效的线程安全。`ConcurrentHashMap`在...理解和掌握其工作原理对于编写高性能并发代码至关重要。

    深入学习java并发包ConcurrentHashMap

    《深入学习Java并发包ConcurrentHashMap》 Java并发包中的ConcurrentHashMap是线程安全的散列映射,它是HashMap的并发版本,适用于多线程...通过理解和掌握其内部机制,开发者能够更好地利用它来优化并发程序的性能。

    深入理解Java内存模型 pdf 超清版

    - Java提供了如`Atomic`系列类、`ConcurrentHashMap`等并发工具,它们基于JMM提供了高效且线程安全的解决方案。 7. **线程安全的实现策略** - 非阻塞同步(如`AtomicInteger`) - 同步块/同步方法(使用`...

    java面试题高级, 对底层高并发深入理解

    在Java面试中,对于高级职位,面试官通常会考察应聘者对Java语言的深入理解和在高并发环境下的处理能力。以下是一些相关的知识点: 1. **JVM内存模型**:了解Java虚拟机(JVM)的工作原理至关重要。JVM内存分为堆...

Global site tag (gtag.js) - Google Analytics