标签:并发 concurrent 线程 高性能 map
ConcurrentHashMap能够做到比较高性能的并发访问。
这里的Segment个数必须为2的n次方,为了之后高效计算要存放的key存放在哪个Segment上(用 << 实现)。
Segment内部拥有一个类型为volatile的HashEntry数组,这是为了能够让其它线程看到最新的值。
ConcurrentHashMap拥有put,get,remove等操作。而原有的扩容操作,为了性能则只针对单个Segment来进行。
关键的Segment相当了ConcurrentHashMap中的子map,它包含了一个HashEntry数组。它的类图如下:
这里关键的Segment类图如下:
HashEntry内部存储了hash值,final的key值,及volatile的value及next值。
这里value及next值是volatile是为实现get操作的不需要加锁提供了基础。
HashEntry类图如下:
下面分别从ConcurrentHashMap创建,往ConcurrentHashMap放入元素,从ConcurrentHashMap取出元素来进行分析。
一.ConcurrentHashMap创建
public ConcurrentHashMap(int initialCapacity,
float loadFactor, int concurrencyLevel) {
if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0)
throw new IllegalArgumentException();
if (concurrencyLevel > MAX_SEGMENTS)
concurrencyLevel = MAX_SEGMENTS;
// Find power-of-two sizes best matching arguments
int sshift = 0;
int ssize = 1;
while (ssize < concurrencyLevel) {
++sshift;
ssize <<= 1;
}
this.segmentShift = 32 - sshift;
this.segmentMask = ssize - 1;
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
int c = initialCapacity / ssize;
if (c * ssize < initialCapacity)
++c;
int cap = MIN_SEGMENT_TABLE_CAPACITY;
while (cap < c)
cap <<= 1;
// create segments and segments[0]
Segment<K,V> s0 =
new Segment<K,V>(loadFactor, (int)(cap * loadFactor),
(HashEntry<K,V>[])new HashEntry[cap]);
Segment<K,V>[] ss = (Segment<K,V>[])new Segment[ssize];
UNSAFE.putOrderedObject(ss, SBASE, s0); // ordered write of segments[0]
this.segments = ss;
}最后将ConcurrentHashMap的segments设置为新创建的Segments数组。
这里可以看到最后将创建的Segment s0是调用UNSAFE.putOrderedObject(ss,SBASE,s0)来将其放入到ss数组中。
这里的UNSAFE.putOrderedObject是JAVA提供的用于直接操作内存的方法,其中参数ss是数组。
UNSAFE.putOrderedObject会延迟更新到内存中,但是由于后续在获取segment数组中的segment时,采用的是UNSAFE.getObjectVolatile,所以能够保证对于segment放入数组的操作对于后续的线程是可见的。
SBASE是ConcurrentHashMap的一个静态final long的值,相当于是Segment数组的首地址。
s0则是创建的需要放入ss数组中的segment实例。这里是将s0放入到ss数组位置0中。
如果提供类似:UNSAFE.putOrderedObject(ss,SBASE+offset,s)表明将元素s放入到数组ss的SBASE+offset位置。
其中这里的offset:
offset=步长*要放在数组第几位
步长一般是在编译期已经确定,这里测试过对于:Double或者Integer等,步长都是4。
深入ConcurrentHashMap一,布布扣,bubuko.com
标签:并发 concurrent 线程 高性能 map
原文地址:http://blog.csdn.net/zhaozhenzuo/article/details/37668697