ConcurrentHashMap源码分析 jdk1.7 个人理解总结
写博客是因为之前本地的笔记老是容易丢失,所以现在抽空把能找到的搬运到博客上,也是为了日后便于查看。个人理解,很可能有错误,大家批判着看
ConcurrentHashMap源码分析
1.数据结构:数组(Segment)+数组(table)+链表
2.Segment中的HashEntry[] table 是被volatile修饰的,直接在内存上操作(确保数据可见性和正确性);
Segment是静态内部类,继承了重入锁ReentranLock,所以想要访问segment片段,线程就必须获得同步锁
3.HashEntry:ConcurrentHashMap的基本数据结构,value和next都用volatile修饰;
每个segment中的数组HashEntry[] table长度必须是2的幂次方,最小为2
4.构造方法:根据给定并发度concurrencyLevel,算出合适的segments数组长度(大于concurrencyLevel的最小的2的幂次方)默认16;
segment[0]初始化,其余的segment是调用ensureSegment方法实现延迟初始化(延迟加载策略)。
5.put<K,V>:根据key的hash值找到对应的segment,
检查segment有没有被初始化,如果没有就调用ensureSegment的方法初始化,并且是以segment[0]为模板进行初始化的,
ensureSegment使用cas方式初始化保证线程安全;
初始化完了再进行put<key,hash,value,fasle>操作
6.put<key,hash,value,fasle>:第一步就是尝试对Segment加锁,如果没有加锁成功,就执行scanAndLockForPut;
scanAndLockForPut自旋获取锁并预先找到新的HashEntry<K,V> node将要put到的位置,并返回node;
7.get:get的时候如果超过重试次数,就会强制对segment加锁,这时本来要延迟创建的segment就会在这个过程中被创建
key和value都不可以为null,key直接使用hash算法,如果为空的话,会NPE,value有一个判断,如果为空就直接NPE;