博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ConcurrentHashMap源码分析
阅读量:6292 次
发布时间:2019-06-22

本文共 2002 字,大约阅读时间需要 6 分钟。

hot3.png

最近,在写一个数据监控项目,涉及到ConcurrentHashMap,之前只是用,虽然没出问题,但是并不是特别清楚里面的原理,所以,这一次,需要把原理弄明白再开始动手。

==============================================

首先,如果输入

map = new ConcurrentHashMap
(512);

我们看初始化的部分:

public ConcurrentHashMap(int initialCapacity) {        if (initialCapacity < 0)            throw new IllegalArgumentException();        int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ?                   MAXIMUM_CAPACITY :                   tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1));        this.sizeCtl = cap;    }

看图走的分支

接下来,计算下tableSizeFor的内容,其中入参为(512+(256)+1)--->769

我们先看tableSizeFor的函数声明

/**     * Returns a power of two table size for the given desired capacity.     * See Hackers Delight, sec 3.2     */

那么,很简单了,769的输出就是1024,所以总体来说,我们一开始参数为512,输出结果为1024.

所以,后面可以考一个面试题,当ConcurrentHashMap的初始化参数为512时,实际的桶个数为多少?

好,接下来,我们继续去执行我们的业务代码。

这里主要使用了merge函数,

private static ConcurrentHashMap
GLOBAL_MAP = null;GLOBAL_MAP = new ConcurrentHashMap
(256);GLOBAL_MAP.merge(key, report, GLOBAL_BI_FUNCTION);

进入merge函数查看代码

int h = spread(key.hashCode());

先计算key.hashCode

算法比较简单,每个String会计算一个哈希值,如果之前计算过了,会缓存起来。

---

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

这个就是根据上面的值计算一个新的值。

其中HASH_BITS的值为

static final int HASH_BITS = 0x7fffffff; // usable bits of normal node hash

---继续执行

进来,因为之前没有初始化过table,所以这里需要初始化,我们看看初始化的代码。

 

执行完后,table就初始化完毕了。

---

然后就执行上面的这行语句。

---

其中n是哈希表的长度,(n-1)&h就是根据哈希值与上桶的总长度,得出一个桶的下标。

这个就不解释了,跟C中的数组一样的原理,现在我们取到了一个桶。

---

上图中,因为刚开始所有的数组元素都为空,所以需要初始化这个数组里的元素不为空。

---进入casTabAt函数,就是给这个空元素赋予一个Node值。

接下来执行

if (delta != 0)            addCount((long)delta, binCount);

这里的delta值为1,所以会执行addCount函数,第一次执行时没有特别的地方,

---接着执行第2次merge操作,如果这次也是执行同一个桶的的操作的话,

可以看到,会锁住这个对象,也就是锁住桶。

下面看看如何降低这个锁粒度的冲突。

f 如果要一样--->h要一样--->key要一样--->结论:同一个key会锁住同一个桶。

---接下来执行

这里就开始执行我们的函数了。

最后看一下自定义的remappingFunction函数的执行条件

哈希值相同,并且(要么key是同一个对象,要么key.equals相同),就认为是找到了这个对象,可以执行merge操作了。

转载于:https://my.oschina.net/qiangzigege/blog/811995

你可能感兴趣的文章
windows下安装redis
查看>>
CentOS7 yum 安装git
查看>>
启动日志中频繁出现以下信息
查看>>
httpd – 对Apache的DFOREGROUND感到困惑
查看>>
分布式锁的一点理解
查看>>
idea的maven项目,install下载重复下载本地库中已有的jar包,而且下载后jar包都是lastupdated问题...
查看>>
2019测试指南-web应用程序安全测试(二)指纹Web服务器
查看>>
树莓派3链接wifi
查看>>
js面向对象编程
查看>>
Ruby中类 模块 单例方法 总结
查看>>
jQuery的validate插件
查看>>
5-4 8 管道符 作业控制 shell变量 环境变量配置
查看>>
Enumberable
查看>>
开发者论坛一周精粹(第五十四期) 求购备案服务号1枚!
查看>>
validate表单验证及自定义方法
查看>>
javascript 中出现missing ) after argument list的错误
查看>>
使用Swagger2构建强大的RESTful API文档(2)(二十三)
查看>>
Docker容器启动报WARNING: IPv4 forwarding is disabled. Networking will not work
查看>>
(转)第三方支付参与者
查看>>
程序员修炼之道读后感2
查看>>