第10讲 | 如何保证集合是线程安全的? ConcurrentHashMap如何实现高效地线程安全?
该思维导图由 AI 生成,仅供参考
典型回答
考点分析
- 深入了解
- 翻译
- 解释
- 总结
ConcurrentHashMap是为了解决传统集合框架在高并发情况下性能低下的问题而设计的线程安全容器类。它采用了精细化的线程安全机制,如基于分离锁实现,以提高并发表现。文章详细介绍了ConcurrentHashMap的设计实现和演进过程,包括早期基于分离锁和volatile字段的实现,以及Java 8及之后版本中利用CAS等操作进行无锁并发操作的优化。此外,文章还提到了ConcurrentHashMap的初始化操作和同步逻辑上的优化。总的来说,ConcurrentHashMap通过精细化的线程安全机制和优化的内部实现,有效提高了在高并发情况下的性能表现。同时,文章还介绍了CounterCell的操作基于java.util.concurrent.atomic.LongAdder进行的,是一种JVM利用空间换取更高效率的方法,利用了内部的复杂逻辑。这些技术特点使得ConcurrentHashMap成为在高并发情况下的性能优秀的选择。
《Java 核心技术面试精讲》,新⼈⾸单¥59
全部留言(67)
- 最新
- 精选
- 徐金铎需要注意的一点是,1.8以后的锁的颗粒度,是加在链表头上的,这个是个思路上的突破。
作者回复: 是的
2018-05-266117 - Sean最近用ConcurrentHashMap的场景是,由于系统是一个公共服务,全程异步处理。最后一环节需要http rest主动响应接入系统,于是为了定制化需求,利用netty写了一版异步http clinet。其在缓存tcp链接时用到了。 看到下面有一位朋友说起了自旋锁和偏向锁。 自旋锁个人理解的是cas的一种应用方式。并发包中的原子类是典型的应用。 偏向锁个人理解的是获取锁的优化。在ReentrantLock中用于实现已获取完锁的的线程重入问题。 不知道理解的是否有误差。欢迎指正探讨。谢谢
作者回复: 正确,互相交流 偏向锁,侧重是低竞争场景的优化,去掉可能不必要的同步
2018-05-28254 - 虞飞老师在课程里讲到同步包装类比较低效,不太适合高并发的场景,那想请教一下老师,在list接口的实现类中。在高并发的场景下,选择哪种实现类比较好?因为ArrayList是线程不安全的,同步包装类又很低效,CopyonwriteArrayList又是以快照的形式来实现的,在频繁写入数据的时候,其实也很低效,那这个类型该怎么选择比较好?
作者回复: 目前并发list好像就那一个,我觉得不必拘泥于list,不还有queue之类,看场景需要的真是list吗
2018-05-2726 - Leiy我感觉jdk8就相当于把segment分段锁更细粒度了,每个数组元素就是原来一个segment,那并发度就由原来segment数变为数组长度?而且用到了cas乐观锁,所以能支持更高的并发,不知道我这种理解对吗?如果对的话,我就在想,为什么并发大神之前没想到这种,哈哈😄,恳请指正。谢谢
作者回复: 基本正确,cas只用在部分场景; 事后看容易啊,说比做容易,😄
2018-05-2913 - coder王您说的synchronized被改进很多很多了,那么在我们平常使用中,就用这个synchronized完成一些同步操作是不是OK?😁
作者回复: 通常是的,前提是JDK版本需要新一点
2018-05-28312 - 约书亚这期内容太难,分寸不好把握 看8的concurenthashmap源码感觉挺困难,网上的博文帮助也不大,尤其是扩容这部分(似乎文章中没提) 求问杨大有没有什么窍门,或者有什么启发性的paper或文章? 可以泛化成,长期对lock free实现多个状态修改的问题比较困惑,希望得到启发
作者回复: 本文尽量梳理了相对比较容易理解的部分;扩容细节我觉得是个加分项,不是每个人都会在乎那么深入;窍门,可以考虑画图辅助理解,我是比较笨的类型,除了死磕,不会太多窍门……
2018-05-269 - mongo请教老师:putVal方法中,什么情况下会进入else if ((fh=f.hash) == MOVED)分支?是进行扩容的时候吗?nextTable是做什么用的?
作者回复: 我理解是的,判断是个ForwardingNode,resize正在进行; nexttable是扩容时的临时过渡
2018-05-265 - mongo请教老师:putVal方法的第二个if分支,为什么要用tabAt?我的认识里直接数组下标寻址tab[i=(n-1) & hash]也是一个原子操作,不是吗?tabAt里面的getObjectVolatle()方法跟直接用数组下标tab[i=(n-1) & hash]寻址有什么区别?
作者回复: 这个有volatile load语义
2018-05-2625 - Xg huang这里有个地方想跟老师交流一下想法, 从文中"所以,ConcurrentHashMap 的实现是通过重试机制(RETRIES_BEFORE_LOCK,指定重试次数 2),来试图获得可靠值。如果没有监控到发生变化(通过对比 Segment.modCount),就直接返回,否则获取锁进行操作。" 可以看出, 在高并发的情况下, "size()" 方法只是返回"近似值", 而我的问题是: 既然只是一个近似值, 为啥要用这种"重试,分段锁" 的复杂做法去计算这个值? 直接在不加锁的情况下返回segment 的size 岂不是更简单? 我能理解jdk开发者想尽一切努力在高性能地返回最精确的数值, 但这个"精确" 度无法量化啊, 对于调用方来说,这个值依然是不可靠的啊. 所以, 在我看来,这种做法收益很小(可能是我也比较懒吧), 或者有些设计上的要点我没有领悟出来, 希望老师指点一下.
作者回复: 这个是在代价可接受情况下,尽量准确,就像含金量90%和99.9%,99.999%,还是有区别的,虽然不是百分百
2018-06-084 - 行者老师麻烦讲讲自旋锁,偏向锁的特点和区别吧,一直不太清楚。
作者回复: 好,后面有章节
2018-05-273