java中ConcurrentHashMap的概念是什么?数据结构是怎样的?

BSO 2020-12-01 14:55:23 java常见问答 7865

相信大家对于java中的一些基础知识或多或少还是有一些了解的,这些知识对于后续学习更加高深的java知识是起到非常重要的奠基作用的。一起来简单了解一下吧。

首先说一下ConcurrentHashMap的概念:

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

在1.8之前:

数据结构:

ConcurrentHashMap是由Segment数组结构和多个HashEntry数组结构组成。Segment是一种可重入锁ReentrantLock,在ConcurrentHashMap里扮演锁的角色,HashEntry则用于存储键值对数据。

一个ConcurrentHashMap里包含一个Segment数组,Segment的结构和HashMap相似,是一种数组和链表结构, 一个Segment里包含一个HashEntry数组,每个HashEntry是一个链表结构的元素, 每个Segment守护者一个HashEntry数组里的元素,当对HashEntry数组的数据进行修改时,必须首先获得它对应的Segment锁。

put和get的时候,都是现根据key.hashCode()算出放到哪个Segment中: ConcurrentHashMap中默认是把segments初始化为长度为16的数组

在1.8后:

变化:

ConcurrentHashMap的JDK8与JDK7版本的并发实现相比,最大的区别在于JDK8的锁粒度更细,理想情况下talbe数组元素的大小就是其支持并发的最大个数

实现:

改进一:取消segments字段,直接采用transient volatile HashEntry[]table保存数据,采用table数组元素作为锁,从而实现了对每一行数据进行加锁,进一步减少并发冲突的概率。

然后说一下,数据结构:

改进二:将原先table数组+单向链表的数据结构,变更为table数组+单向链表+红黑树的结构。对于hash表来说,最核心的能力在于将key hash之后能均匀的分布在数组中。

概念:

JDK1.8的实现已经摒弃了Segment的概念,而是直接用Node数组+链表+红黑树的数据结构来实现,并发控制使用Synchronized和CAS来操作,整个看起来就像是优化过且线程安全的HashMap,虽然在JDK1.8中还能看到Segment的数据结构,但是已经简化了属性,只是为了兼容旧版本。

一些成员:

Node是ConcurrentHashMap存储结构的基本单元,继承于HashMap中的Entry,用于存储数据。就是一个链表,但是只允许对数据进行查找,不允许进行修改通过TreeNode作为存储结构代替Node来转换成黑红树。

TreeBin:

TreeBin就是封装TreeNode的容器,它提供转换黑红树的一些条件和锁的控制。

// 读写锁状态
static final int WRITER = 1; // 获取写锁的状态
static final int WAITER = 2; // 等待写锁的状态
static final int READER = 4; // 增加数据时读锁的状态最后是,构造器

public ConcurrentHashMap(){}初始化其实是一个空实现, 初始化操作并不是在构造函数实现的,而是在put操作中实现。 还提供了其他的构造函数,有指定容量大小或者指定负载因子,跟HashMap一样。

上文中的相关知识就是为大家详细介绍java中ConcurrentHashMap的内容了。具体的描述还是非常详细的,大家可以多看看。想要了解更多java常见问题,敬请关注奇Q工具网。

推荐阅读:

Concurrenthashmap锁的实现原理有哪些?它又有什么实现方法?

java HashMap的树化与还原是什么?还有哪些面试题?

java中HashMap的扩容机制怎么实现?实例展示