首先,concurrenthashmap是线程安全的,通过把整个map划分为不同的segment来减少在读操作的时候加锁,从而提高并发度
1、concurrenthashmap底层是一个segment数组,每个segment底层又是一个hashEntry数组,segment继承了reentrantlock类来实现锁操作
2、concurrenthashmap的并发度concurrentlevel可以在初始化时进行制定,然后会根据concurrentlevel来生成segment数组的长度,segment数组的长度为大于等于并发度的最小的2的n次方。之后随着容量的增加,segment数组长度并不会增加,rehash的操作只会在各个segment内进行,从而避免影响别的segment,减少rehash的代价。
3、每个segment中数组的长度初始时候根据总容量除以segment数量得到,初始长度为大于相除结果的最小的2的n次方,然后在rehash的时候长度会每次乘2
4、size操作:会先进行未加锁的统计操作,然后比较两次统计的结果一致的话就返回,否则再次尝试,若尝试若干次还未成功就对所有segment全部加锁来进行统计操作。
5、get与put的过程都要先定位到segment然后再定位到segment内部的hashentry数组的具体位置
其中定位到segment的操作:(hash >>> segmentShift) & segmentMask 其实就是用hash值的前n位与segment数组长度2^n-1进行与操作
定位到segment中具体entry的操作与hashmap中一致:hash & (tab.length - 1),其实就是mod操作,只不过这样效率更高一些
6、get操作的时候,找到对应entry后直接返回,不需加锁,但是当得到的value为null时需要加锁
7、put操作的时候,先找到对应的segment然后加锁,先看看是否需要rehash,然后进行操作,之后unlock