ConcurrentHashMap的实现使用了一个包含16个锁的Array,每一个锁都守护Hash Bucket的1/16,Bucket N由第N mod 16个锁来守护。
public class StripedMap{
//同步策略:buckets[n]由lock[n%N_LOCKS]保护
private static final int N_LOCKS=16;
private final Node[] buckets;
private final Object[] locks;
private static class Node{...}
public StripedMap(int numBuckets){
buckets=new Node[numBuckets];
locks=new Object[N_LOCKS];
for(int i=0;i<N_LOCKS;i++){
locks[i]=new Object();
}
}
public final int hash(Object key){
return Math.abs(key.hashCode()%buckets.length);
}
public Object get(Object key){
int hash=hash(key);
synchronized(locks[hash%N_LOCKS]){
for(Node m=buckets[hash];m!=null;m=m.next){
if(m.key.equals(key)){
return m.value;
}
}
}
return null;
}
public void clear(){
for(int i=0;i<buckets.length;i++){
synchronized(locks[i%N_LOCKS]){
buckets[i]=null;
}
}
}
}
上面的例子是基于哈希的 map 中使用分离锁。
如果由你来实现HashMap,你会遇到一个问题,size方法如何计算Map条目的大小?最简单的方法是每次调用的时候数一遍。或者在put和remove时加入一个计数器。在单线程或完全同步的实现中,一个独立的计数器能够提高size和siEmpty的速度,但是会影响到可伸缩性,因为每一个修改map