concurrenthashmap
1.7:先扩容后插数据,segment(hashtable中syn锁住这个map)+hashentry+unsafe;node和hashentry的内容一样,但是HashEntry是一个内部类;需要定位2次(segments[i],segment中的table[i]);concurrentHashMap 使用的分段锁,如果一个线程占用一段,别的线程可以操作别的部分;
1.8:先插数据后扩容,synchronized+cas+node+unsafe,使用synchronized+cas代替segment,锁力度更小,并且不是每次都加锁,cas尝试失败再加锁;先拿到根据rehash值定位,拿到table[i]的首节点first;hashtable通过synchronized修饰方法 来保证线程安全,concurrenthashmap通过synchronized同步代码块和cas操作来实现线程安全;通过使用synchroized关键字来同步代码块,而且只是在put方法中加锁,在get方法中没有加锁;简化结构,put和get不用二次哈希,一把锁只锁住一个链表或者一棵树,并发效率更加提升;
hashmap
1.7:头7尾8,put可能引起死循环;
1.8:头7尾8,put可能造成数据覆盖;扩容优化:一个链表分成高位低位两组去迁移,避免死环问题,也不需要hash;
// JDK 1.8以后的HashMap里面的一段源码
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h ››› 16);
}
^:异或运算,相同为0,不同为1;
0^0->0
1^1->0
0^1->1
››› 16:右移16为,hashcode(32位)高16位->低16位,高16位补0;
hash算法的优化:对每个hash值,在他的低16位中,让高低16位进行了异或,让他的低16位同时保持了高低16位的特征,尽量避免一些hash值后续出现冲突,大家可能会进入数组的同一个位置;
寻址算法的优化:用与运算替代取模,提升性能;