在ConcurrentHashMap中,通过Unsafe类的cas操作来设置或获取segment[j]的值。代码如下:
而SBASE取值为:
UNSAFE.arrayBaseOffset用来获取数组第一个元素的偏移地址。通过该偏移地址可以获取或设置数组的第一个元素。
SSHIFT取值为:
UNSAFE.arrayIndexScale用来计算一个数组元素的引用占的字节数,32位为4字节,64位为8字节。
正常来说,计算第j个偏移地址的公式为:
arrayBaseOffset + j * (arrayIndexScale)
但在ConcurrentHashMap中是通过以下公式来的,如下:
arrayBaseOffset + j << (31 - Integer.numberOfLeadingZeros(arrayIndexScale) )
公式解释如下:
(1)Integer.numberOfLeadingZeros获取int的最高非零位前面的0的个数。
(2) (31 - Integer.numberOfLeadingZeros(arrayIndexScale) )为j需要左移的位数。左移多少位,表示乘以多少个2。
假设arrayIndexScale为4,它的二进制表示如下:
00000000000000000000000000000100
Integer.numberOfLeadingZeros(arrayIndexScale) 为29
31 - Integer.numberOfLeadingZeros(arrayIndexScale) =31-29=2
而左移2位,则好表示了j*4的计算结果。
由此可见,在ConcurrentHashMap中,通过位移及减法操作来取代了乘法运算,大大提高了效率。