ConcurrentHashMap如何实现高效地线程安全?

 我来答
羊羊0531
2021-12-21 · 超过37用户采纳过TA的回答
知道小有建树答主
回答量:128
采纳率:0%
帮助的人:7.4万
展开全部
如何保证容器是线程安全的? ConcurrentHashMap如何实现高效地线程安全?
Java提供了不同层面的线程安全支持。在传统集合框架内部,除了Hashtable等同步容器,还提供了所谓的同步包装器(Synchronized Wrapper),我们可以调用Collections工具类提供的包装方法,来获取一个同步的包装容器(如Collections.synchronizedMap),但是它们都是利用非常粗粒度的同步方式,在高并发情况下,性能比较低下。

另外,更加普遍的选择是利用并发包提供的线程安全容器类,它提供了:

各种并发容器,比如ConcurrentHashMap、 CopyOnWriteArrayList。
各种线程安全队列(Queue/Deque),如ArrayBlockingQueue、 SynchronousQueue。
各种有序容器的线程安全版本等。
1.为什么需要ConcurrentHashMap?
Hashtable本身比较低效,因为它的实现基本就是将put、 get、 size等各种方法加上“synchronized”。简单来说,这就导致了所有并发操作都要竞争同一把锁,一个线程在进行同
步操作时,其他线程只能等待,大大降低了并发操作的效率。

个人理解
就是更细粒度的加锁机制来实现更大程度的共享。

2.ConcurrentHashMap分析
ConcurrentHashMap的设计实现其实一直在演化。

1.7
put加锁
通过分段加锁segment,一个hashmap里有若干个segment,每个segment里有若干个桶,桶里存放K-V形式的链表, put数据时通过key哈希得到该元素要添加到的segment,
然后
对segment进行加锁,然后在哈希,计算得到给元素要添加到的桶,然后遍历桶中的链表,替换或新增节点到桶中
size
分段计算两次,两次结果相同则返回,否则对所以段加锁重新计算
1.8
put CAS 加锁
1.8中不依赖与segment加锁,segment数量与桶数量一致;
首先判断容器是否为空,为空则进行初始化利用volatile的sizeCtl作为互斥手段,如果发现竞争性的初始化,就暂停在那里,等待条件恢复,否则利用CAS设置排他标志
(U.compareAndSwapInt(this, SIZECTL, sc, -1)) ;否则重试
对key hash计算得到该key存放的桶位置,判断该桶是否为空,为空则利用CAS设置新节点
否则使用synchronize加锁,遍历桶中数据,替换或新增加点到桶中
最后判断是否需要转为红黑树,转换之前判断是否需要扩容
size
利用LongAdd累加计算
ConcurrentHashMap使用要点
ConcurrentHashMap使用要点

ConcurrentHashMap允许一边更新、一边遍历,也就是说在Iterator对象遍历的时候,ConcurrentHashMap也可以进行remove,put操作,且遍历的数据会随着remove,put操作产出变化
摔现斩4
2021-12-21 · TA获得超过364个赞
知道小有建树答主
回答量:283
采纳率:57%
帮助的人:64.1万
展开全部
读的时候用volatile保证可见性,使读到的数据永远是最新的

写的时候用分段锁只对部分数据加锁
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式