ConcurrentHashMap类继承至AbstractMap 实现接口ConcurrentMap,Serializable
这个类有以下主要的几个静态变量
DEFAULT_INITIAL_CAPACITY=16 初始化数组长度
DEFAULT_LOAD_FACTOR=0.75 默认装载因子
DEFAULT_CONCURRENCY_LEVEL=16 默认并发级别
MAXIMUM_CAPACITY=1<<30 最大数组长 1<<30
MIN_SEGMENT_TABLE_CAPACITY=2 最小桶长度
MAX_SEGMENTS=1<<16 最大桶数量
接下来是ConcurrentHashMap的构造器
1.可以注意到其中的运算 sshift是并发级别的角标 注意 这里的concurrencyLevel是2的倍数
ssize可以近似看作是concurrencyLevel
2。创建了一个桶对象 s0,和一个桶的数组长度为ssize
这里的HashEntry结构如图
四个变量分别为 key,(volatile修饰保证内存可见性)value,key的hash值(hash) 还有一个用volatile变量修饰的HashEntry元素指针 指向下一个元素
桶segment的类结构如下
桶的主要元素 是一个HashEntry的数组变量和一切其他信息
所以 整个ConcurrentHashMap的结构是一个数组(segment)数组的每一个元素还是一个(HashEntry)数组
接下来看一下put方法
这里的seqmentShift是通过并发等级得到的值 并发等级为N
则segmentShift=32-a,这里得a=log2 N。2为底N为幂 的对数值
这里的J相当于取 他的key的hash值得高a位
通过ensureSegment方法去获取 hash值所在得桶segment对象 注意 在ConcurrentHashmap里面获取对象都是通过UNSAFE.getObjectVolatile去获取得 并且通过CAS(compareAndSwap)算法 去比较赋值 这是保证在高并发下数据保持一致得一种算法
CAS算法 是 有三个值 一个原始值K,一个修改值B,一个预估值A
在修改得时候 先比较原始值 和预估值(在预估值上进行计算得到修改值),当且这两个值相等的时候,才将修改值 写入内存
可以看到
1.加锁
2.调用桶 segment得put方法,通过拿到得桶对象,获取第一个HashEntry数组元素,依次往下遍历,第一个IF判断里是HashEntry[] 里有相同得Key值元素得时候 进行值替换操作 并且控制角标往数组下方移动
3.else里面则是当角标移动到数组最后一位得时候进行元素得新建操作
4.解锁
可以看到,整个ConcurrentHashMap是一个数组加数组得结构
其中HashEntry 在内存上连续 在结构上除了可以通过index关联 也通过next指针关联在一起
在对每一个桶(segment)操作得时候 对其中得HashEntry[](表结构)会进行加锁(trylock)和解锁(unlock)操作 这就是ConcurrentHashMap得分段锁机制。将每一个桶单独做成一个HashMap结构 在高并发得时候 以表结构为单位进行操作。并且通过CAS算法 确保了数据得一致性。所以 ConcurrentHashMap相较于Hashtable而言是效率更高得 相对于HashMap而言 是线程安全得