返回

给ConcurrentHashMap的循环链表画个思维导图

后端

在高并发场景下,为了保证HashMap的线程安全,JDK1.7版本提供了ConcurrentHashMap类。与HashMap相比,ConcurrentHashMap引入了分段锁(Segment)的机制,从而支持高并发场景下对HashMap的并发操作。在ConcurrentHashMap的内部,仍然采用数组(bucket)+链表的方式来存储键值对。当某个桶(bucket)中的元素数量超过一定阈值时,这个桶就会被转换为链表结构。今天这篇文章的主要内容,就是关于ConcurrentHashMap的循环链表。

ConcurrentHashMap的结构

ConcurrentHashMap由若干个Segment(分段)组成,每个Segment维护了一个HashTable,其中存储着键值对。Segment之间使用锁来隔离,从而实现线程安全。Segment中的HashTable使用数组(bucket)+链表的方式来存储键值对,如下图所示:

图片:ConcurrentHashMap的结构

为什么使用链表而不是数组?

在ConcurrentHashMap中使用链表而不是数组的主要原因是,链表可以更好地处理元素数量较多的情况。当元素数量较少时,数组的查找效率更高。但是,当元素数量较多时,数组的查找效率会下降。这是因为,当在数组中查找一个元素时,需要遍历整个数组。而链表则不同,在链表中查找一个元素只需要遍历到该元素所在的结点即可。因此,当元素数量较多时,链表的查找效率更高。

循环链表的实现细节

ConcurrentHashMap的循环链表是一个单向循环链表,它使用Node类来存储键值对。Node类包含三个属性:key、value和next。其中,key和value分别是键和值,next指向下一个结点。

循环链表的实现非常简单。在ConcurrentHashMap中,有一个head节点,它指向第一个结点。当需要向链表中添加一个新的结点时,只需要将新结点的next指针指向head节点,然后将head节点指向新结点即可。当需要从链表中删除一个结点时,只需要将该结点的next指针指向该结点的上一个结点即可。

循环链表的好处和局限性

循环链表的主要好处是,它可以更好地处理元素数量较多的情况。当元素数量较少时,数组的查找效率更高。但是,当元素数量较多时,数组的查找效率会下降。这是因为,当在数组中查找一个元素时,需要遍历整个数组。而链表则不同,在链表中查找一个元素只需要遍历到该元素所在的结点即可。因此,当元素数量较多时,链表的查找效率更高。

循环链表的主要局限性是,它不能像数组那样支持随机访问。这是因为,在链表中查找一个元素时,需要从头结点开始遍历。如果链表中的元素数量较多,那么查找效率就会很低。

循环链表在ConcurrentHashMap中的应用场景

ConcurrentHashMap的循环链表主要用于存储元素数量较多的桶(bucket)。当某个桶(bucket)中的元素数量超过一定阈值时,这个桶就会被转换为链表结构。这样可以提高对该桶的并发访问效率。

总结

ConcurrentHashMap的循环链表是一个非常重要的数据结构,它可以更好地处理元素数量较多的情况。在ConcurrentHashMap中,循环链表主要用于存储元素数量较多的桶(bucket)。这样可以提高对该桶的并发访问效率。