ConcurrentHashMap的实现原理是分段锁?你Out了
创始人
2024-02-05 22:33:54
0

在这里插入图片描述

前言

Java后端开发面试的时候,一场好的面试,是无论如何也绕不开并发编程的。并发编程里面往往有个很重要的类可能会被拿出来探讨:ConcurrentHashMap。
ConcurrentHashMap是HashMap的线程安全版。大家都知道HashMap的高性能,但是HashMap不是线程安全的。所以为了解决这个问题,就推出了Concurrent版本。

在和面试官探讨这个问题的时候,大家一般都会把分段锁Segment的实现原理拿出来大讲特讲(因为除了这个分段式锁外,好像别的也没有什么不同的)。

模拟面试场景

面试官:请简述下ConcurrentHashMap的实现原理。
面试者
  1、ConcurrentHashMap是由Segment数组和HashEntry数组组成。它内部细分成了若干个小的HashMap,每个小的HashMap被称为段(Segment),默认情况下,一个ConcurrentHashMap被细分为16个Segment。
  2、Segment是一种可重入锁ReentrantLock,它在ConcurrentHashMap中扮演锁的角色;HashEntry用来存储键值对数据。
  3、一个 ConcurrentHashMap 里包含一个 Segment 数组,Segment 的结构和 HashMap类似,是一种数组+链表结构。
  4、每个Segment里包含一个HashEntry数组,当要对HashEntry数组的数据进行修改时,必须要先获得它对应的Segment锁。

真正的ConcurrentHashMap

此时,是不是感觉自己答的很溜?这个问题中的重要点都回答了。
但是,这真的是你用的ConcurrentHashMap吗?还是你Out了?

其实,你还真是Out了。上面的回答是没问题的,但是知识点Out了。这个ConcurrentHashMap分段锁的实现是JDK1.7的了(网上的很多知识都是这样的)。JDK1.8之后的实现有了很大的改变了

ConcurrentHashMap源码

说多了浪费口水,还是直接看源码吧。
ConcurrentHashMap代码在java.util.concurrent包中(不要搞错了)

Node部分源码

public class ConcurrentHashMap extends AbstractMapimplements ConcurrentMap, Serializable {/* ---------------- Constants -------------- *///...  省略部分代码//实现重点代码/* ---------------- Nodes -------------- *//*** Key-value entry.  This class is never exported out as a* user-mutable Map.Entry (i.e., one supporting setValue; see* MapEntry below), but can be used for read-only traversals used* in bulk tasks.  Subclasses of Node with a negative hash field* are special, and contain null keys and values (but are never* exported).  Otherwise, keys and vals are never null.*/static class Node implements Map.Entry {final int hash;final K key;volatile V val;volatile Node next;Node(int hash, K key, V val, Node next) {this.hash = hash;this.key = key;this.val = val;this.next = next;}public final K getKey()       { return key; }public final V getValue()     { return val; }public final int hashCode()   { return key.hashCode() ^ val.hashCode(); }public final String toString(){ return key + "=" + val; }public final V setValue(V value) {throw new UnsupportedOperationException();}public final boolean equals(Object o) {Object k, v, u; Map.Entry e;return ((o instanceof Map.Entry) &&(k = (e = (Map.Entry)o).getKey()) != null &&(v = e.getValue()) != null &&(k == key || k.equals(key)) &&(v == (u = val) || v.equals(u)));}/*** Virtualized support for map.get(); overridden in subclasses.*/Node find(int h, Object k) {Node e = this;if (k != null) {do {K ek;if (e.hash == h &&((ek = e.key) == k || (ek != null && k.equals(ek))))return e;} while ((e = e.next) != null);}return null;}}//...  省略部分代码

我们会发现,ConcurrentHashMap类中中没有找到Segment的实现的影子。而是在类中发现了很多使synchronized的方式来实现的。

put源码

我们看下常用的put方法的实现。发现使用的是synchronized来实现的。

	public V put(K key, V value) {return putVal(key, value, false);}/** Implementation for put and putIfAbsent */final V putVal(K key, V value, boolean onlyIfAbsent) {if (key == null || value == null) throw new NullPointerException();int hash = spread(key.hashCode());int binCount = 0;for (Node[] tab = table;;) {Node f; int n, i, fh;if (tab == null || (n = tab.length) == 0)tab = initTable();else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {if (casTabAt(tab, i, null,new Node(hash, key, value, null)))break;                   // no lock when adding to empty bin}else if ((fh = f.hash) == MOVED)tab = helpTransfer(tab, f);else {V oldVal = null;synchronized (f) {if (casTabAt(tab, i, null, r)) {//...省略代码}
···

CAS部分代码

    static final  boolean casTabAt(Node[] tab, int i,Node c, Node v) {return U.compareAndSwapObject(tab, ((long)i << ASHIFT) + ABASE, c, v);}

总结

新版的ConcurrentHashMap和Segment分段锁没有任何关系。它的实现方式和HashMap有点大同小异:数组+链表+红黑树。

更新后的变化

类型JDK1.7JDK1.8
数据结构Segment分段锁数组+链表+红黑树
线程安全机制segment的分段锁机制CAS+Synchorized机制
锁的粒度每段Segment加锁,粒度大每个Node元素加锁,粒度更细
遍历时间复杂度O(n)O(logN)
好了,如果你把上面新的知识结合老的知识一起给到面试官,我想面试官肯定会想,这家伙是个可造之才,让HR通知他,明天赶紧来上班。

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...