1、典型回答
分段锁是一种将锁细化到每个段(Segment) 级别的锁设计。在 ConcurrentHashMap 中,它将整个数据结构分成多个段,每个段只锁定自己的一部分数据。每个段可以看作是一个独立的分组,只锁定该段(Segment)内部的数据操作,不同的段之间可以并行地进行操作。
如下图所示:
(哈希桶),相当于给多个 Entry 进行了分组操作,这样比给所有 Entry 加锁效率要高很多,currentHashMap 相比于 Hashtable 性能高的原因,Hashtable 是给所有的 Entry 加同-把锁来操作的,而 ConcurrentHashMap 将 Entry 分成了多 Segment,每个 Segment 单独加锁,这样就可以实现多个 Segment 一起并发执行了,所以 ConcurrentHashMap 的效率也会越高
2、全面剖析
分段锁是一种将锁细化到每个段(Seament)级别的锁设计。在 ConcurentHashMap 中,它将整个数据结构分成多个段,每个段只锁定自己的一部分数据
分段锁的实现源码如下:
final V put(K key, int hash, V value, boolean onlyIfAbsent) {
// 在往该 segment 写入前,先确保获取到锁
HashEntry<K, V> node = tryLock() ? null : scanAndLockForPut(key, hash, value);
V oldValue;
try {
// Segment 内部数组
HashEntry<K, V>[] tab = table;
int index = (tab.length - 1) & hash;
HashEntry<K, V> first = entryAt(tab, index);
for (HashEntry<K, V> e = first;;) {
if (e != null) {
K k;
// 更新已有值...
} else {
// 放置 HashEntry 到特定位置,如果超过阈值则进行 rehash
// 忽略其他代码..
}
}
} finally {
// 释放锁
unlock();
return oldValue;
}
}
以上述源码我们可以看出,Segment 本身是基于 ReentrantLock 实现的加锁和释放锁的操作,这样就能保证多个线程同时访问 ConcurrentHashMap 时,同一时间只有一个线程能操作相应的节点,这样就保证了ConcurrentHashMap 的线程安全了