ConcurrentHashMap为什么能提高并发性,原理是什么?

ConcurrentHashMap是线程安全的容器。

ConcurrentHashMap是基于乐观锁实现线程安全的。

ConcurrentHashMap是基于CAS算法和volatile实现线程安全的。


java1.8版本对ConcurrentHashMap进行了较大的优化,我们先看1.8之前的ConcurrentHashMap,然后文章的后半部分再来研究1.8版本的ConcurrentHashMap。


我们都知道,ConcurrentHashMap使用了分段map的思想,也就是segment,segment是如何提高并发性的?又是如何保证线程安全的?


1,分段锁技术

什么是segment呢,ConcurrentHashMap会把数据分段存储,然后每段数据分别加锁。看源码可以发现,其实就是遍历node的时候,加上synchronized关键字,而Hashtable是在整个put方法上加上synchronized关键字。

数据分段加锁以后,由于一个线程只锁定了某一段数据,所以其他线程还可以访问其他数据。这样就达到了提高并发能力的要求。

为了理解更加深入,我们考虑一下下面这种场景,如果两个线程要获取map中的同一个key,是否能同时访问呢?也就是说,这种情况下能并发执行吗?segment到底是如何分段的?如果我的map中只有2个兼职对,难道也要分成16个segment吗?


从代码的角度来说,Segment是ConcurrentHashMap的一个内部类,继承了重入锁ReentrantLock,实现了序列化接口。


2,put方法

先通过segmentFor(hash)定位到数据所在的分段,然后调用分段的put方法。put方法的实现使用的是加锁操作,这里加的是重入锁,也就是说put方法没有使用CAS乐观锁,而只是使用了segment分段处理。java1.8开始使用CAS乐观锁代替RentrantLock



3,get方法


4,remove方法

先根据key定位segment,然后调用segment的containKey(key, hash, null)方法。

remove方法的实现使用的是加锁操作,这里加的是重入锁,也就是说remove方法没有使用CAS乐观锁,而只是使用了segment分段处理。


5,size方法

size方法统计的是整个map的大小,所以必须要统计所有的segment大小,然后求和。Segment里面有一个count变量,这个变量是volatile类型的,也就是内存可见的,但是在多线程环境下,不是线程安全的。因为你拿到count以后还要求和,虽然拿到的那一刻,是线程安全的,但是还要求和,求和操作的过程中如果count改变了,最后统计的结果就不准确了。

为了解决这个问题,ConcurrentHashMap提供了这样一种思路:累加过程中,累加结果发生改变的概率很小,所以

ConcurrentHashMap的做法是先在segment不加锁的情况下,进行两次累加操作,如果累加结果一致,OK,直接把累加结果当做size返回。如果累加结果不一致,则把所有segment的put方法、remove方法、clear方法锁住,然后在获取count进行累加操作。


6,containKey方法

先根据key定位segment,然后调用segment的containKey(key, hash)方法。

这个方法不存在线程安全的问题。源代码如下:

图片发自简书App


二,java1.8 ConcurrentHashMap源码解析


1,put方法


put方法

1,如果Node数组为空,则初始化,也就是说map中Node的初始化是延迟的,知道put操作的时候,才真正初始化。

2,spread(key.hashcode()),二次hash,减少hash碰撞。

3,如果桶的深度大于1,需要追加到链表或者红黑树时,使用synchronized进行同步。ConcurrentHashMap主要是这个操作使用了synchronized进行同步,其他都是使用RentrantLock。



三,Java1.8对ConcurrentHashMap的优化


1,使用CAS乐观锁和volatile代替RentrantLock


2,spread二次哈希进行segment分段。


3,stream提高并行处理能力。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容