ConcurrentHashMap的实现原理。
ConcurrentHashMap定义了Segment内部类,看一下代码:
//Segment继承了ReentrantLock重入锁(这个概念这次先不看)
static final class Segment<K,V> extends ReentrantLock implements Serializable {
//HashEntry与HashMap中类似,可以理解为一个单向链表元素,作为存放相同hash值,不同key的键值对,因为:ConcurrentHashMap通过数组形式存放多个Segment,用key的hash值做一次再hash,当做下标,识别当前键值对存放在segments数组中的哪个segment里。
//这样一个Segment就相当于一个HashMap
transient volatile HashEntry<K,V>[] table;
V put(K key, int hash, V value, boolean onlyIfAbsent) {
//在对Segment进行操作时,对当前对象Segment加锁
lock();
try {
//数据操作
} finally {
unlock();
}
}}
ConcurrentHashMap通过数组形式存放多个Segment,用key的hash值做一次再hash当做下标识别当前键值对存放在哪个segment里。
final Segment<K,V>[] segments;
public V put(K key, V value) {
if (value == null)
throw new NullPointerException();
//用key的hashCode再做一次hash
int hash = hash(key.hashCode());
return segmentFor(hash).put(key, hash, value, false);
}
在对segment元素进行操作时加锁,这样当其它人线程操作当前ConcurrentHashMap对象时,只要key1的hash值(hash(key1.hashCode()))与加锁key2的值(hash(key2.hashCode()))不同,就可以直接操作其它Segment元素。
示意图:
ConcurrentHashMap结构:
ConcurrentHashMap 有 16 个 Segments ,所以理论上,这个时候,最多可以同时支持 16 个线程并发写,只要它们的操作分别分布在不同的 Segment 上。这个值可以在初始化的时候设置为其他值,但是一旦初始化以后,它是不可以扩容的。