HashMap->ConcurrentHashMap
简单认识
什么是hash呢?
就是把任意长度的输入,通过散列算法换成固定长度的输出。
常用的hash函数:
直接取余法,乘法取整法,平方取中法。
hash冲突怎么解决呢?
开放寻址,在散列,连地址法,常见的有MD5,SHA-1,不可逆。
不安全,撞库可以找到,加密加盐值。
HashMap
大家都是hashMap是不安全的,但是它为什么不是安全的呢?
hashMap的一次扩容,取当前table的2倍作为新table的大小。在多线程的场景下,一个线程在执行中被挂起,一个线程完成了扩容。这时第一个线程又被唤起,执行后面的扩容动作。因为是头插法,next的引用会形成循环引用,造成死循环。
当去get一个不存在元素的时候会产生死循环。
JDK1.7中的ConcurrentHashMap中的实现
除了常见的get,put方法之外,还添加了putIfAbsent方法。putIfAbsent时,有这个key,返回这个key对应的值,没有的话,添加返回null。
segment[],segment,其实就是个可重入锁。
一个segment中,对应一个hashEntry[]。
一旦初始化ConcurrentHashMap之后,segment[]数组大小固定,扩容的其实是hashEntry[]数组。segment[],hashEntry[]的数组大小,都是对应的初始值的最小2的N次方。
get方法
没有加锁,为什么还能保证线程是安全的呢?
ConcurrentHashMap的里面的元素值,都添加了volidate的属性值,保证线程之间的可见性。
一个key怎么两次hash定位到值呢?
高位定位到是哪个segment,全部定位hashentry中的位置。
后续put,以及ConcurrentHashMap在JDK1.8中的特性,实现是什么?