美文网首页
CurrentHashMap源码分析(2018-08-11)

CurrentHashMap源码分析(2018-08-11)

作者: 有章 | 来源:发表于2018-08-11 14:08 被阅读0次

1.7实现

采用segment数组分段锁机制,实现并发的更新,底层采用数组+链表+红黑树

每一个segment相当于一个hashMap

1.8实现

采用CSA和Synchronized机制,底层同样采用了数组+链表+红黑树

初始化:initTable()

当tab==null || tab.length()==0时 while循环中执行;

table只在put方法中初始化1次,初始化的线程将sizeCtl设置为-1,

U.compareAndSwapInt(this, SIZECTL, sc, -1)

其他线程判断sizeClt<0,则THhread.yield()让出时间片


putVal()方法

1.hash算法

static final int spread(int h) {return (h ^ (h >>> 16)) & HASH_BITS;}

2.table中定位索引位置,n是table的大小  int index = (n - 1) & hash

3.获取table中对应索引的元素f

Doug Lea采用Unsafe.getObjectVolatile来获取,为什么不直接从每个线程的table[index]中取?

因为每个线程中取到的table的元素,有可能不是最新的,而Unsafe.getObjectVolatile()可以直接从内存中获取最新的元素

【红黑树】

如果链表结构中元素超过TREEIFY_THRESHOLD阈值,默认为8个,则把链表转化为红黑树,提高遍历查询效率,效率为log(n)

链表转树阈值:8

树转链表阈值:6

树根节点的hash值为:-2

【sizeCtl】

sizeCtl是控制标识符,不同的值表示不同的意义。

负数代表正在进行初始化或扩容操作

-1代表正在初始化

-N 表示有N-1个线程正在进行扩容操作

正数或0代表hash表还没有被初始化,这个数值表示初始化或下一次进行扩容的大小,类似于扩容阈值。它的值始终是当前ConcurrentHashMap容量的0.75倍,这与loadfactor是对应的。实际容量>=sizeCtl,则扩容(sc = n - (n >>> 2); //无符号右移2位,此即0.75*n )

参考博客:

JDK 1.8 ConcurrentHashMap 源码剖析

相关文章

网友评论

      本文标题:CurrentHashMap源码分析(2018-08-11)

      本文链接:https://www.haomeiwen.com/subject/rfldbftx.html