ConcurrentMap extents Map,增加了一些模板方法,比如compute、forEach等,整体说就是线程安全的KV存储。
实现有三个:ConcurrentHashMap、ConcurrentNavigableMap、ConcurrentSkipListMap
ConcurrentHashMap
大名鼎鼎的面试题,呵呵呵。全面介绍就靠别人了。JDK1.8应该是没有二次分桶了,而是用解决冲突的Entry作为锁粒度了。
大小一定是2的指数,计算大小的时候用了神奇位运算
private static final int tableSizeFor(int c) {
int n = c - 1;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}分桶靠位运算,但只靠int的低16位,所以会做高低16位的亦或后再使用
- get就是找到桶,挨个比对。唯一线程安全的地方,是从数组(存储)中读桶的时候,用的是Unsafe.getObjectVolatile。遇到hash值为负(非正常节点时),使用代理的方式,让Node负责去找值。这个Strategy模式棒
- put的时候,只有在出现碰撞的时候才会加一个普通的synchronized锁。初始化用的是标志位;新建桶是CAS
- 读写如果在扩容时,据说是靠一个bit位去映射新老桶,但是映射方法没参透——2298行,我的位操作弱爆了
- compute类似put的实现,只不过是应用了传入的方法
ConcurrentNavigableMap
小哥说增加了一些接口。这本身只是个新interface,实现只有一个ConcurrentSkipListMap。
ConcurrentSkipListMap
如名,是个跳表,非常有意思的一个数据结构。代码里各种用label的地方,小的表示看不懂了。。。