A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

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 )




0 个回复

您需要登录后才可以回帖 登录 | 加入黑马