博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
面试刷题10:ConcurrentHashMap如何保证线程安全?
阅读量:4210 次
发布时间:2019-05-26

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

image.png

集合框架中的HashTable,Stack,以及同步包装集合在高并发场景下都非常低效,java提供了并发包应对高并发场景。
我是李福春,我在准备面试,今天的问题是?
java提供了哪些并发的容器?ConcurrentHashMap如何保证线程安全?

java体系中的并发容器

java体系中有如下同步容器:
1, HashTable,Stack 同步容器,内部使用sychronized关键字保证同步操作;
2,同步包装器Collections.synchronizedMap(),内部也使用sychronized关键字保证同步操作;

3,并发包提供的同步容器,比如ConcurrentHashMap , CopyOnWriteArrayList , ArrayBlockingQueue,SynchronizedQueue

ConcurrentHashMap的同步分析

为何会出现ConcurrenHashMap?
1, HashTable在高并发场景下性能低下;
2,HashMap 不是线程安全的容器;
3,同步包装器虽然使用同步方法快提升了部分性能,但是还是不适合高并发场景下的性能需求;
接下来回答问题,ConcurrentHashMap如何保证线程安全?

java7

java7版本使用的是分离锁(segment)实际上是一种再入锁(RetrantLock)来保证线程安全;
segment的数量是concurrentLevel决定,默认值是16;
扩容的时候是针对单个segment扩容的,写操作也是,修改数据的时候锁定的部分,所以比较高效;
但是后去size可能不太准确。

数据结构如下图:

image.png

java8

java8中segment依然存在,不过不起结构上的作用,只起到保证序列化的兼容性。
内部使用volatile来保证数据存储的可见性;
利用CAS操作,在特定场景下进行无锁并发操作,内部的锁实际用的是syncronized;
因为在jdk8中,syncronized已经得到性能的优化,并且对比再入锁可以减少内存消耗。
见代码:

final V putVal(K key, V value, boolean onlyIfAbsent) { if (key == null || value == null) throw new NullPointerException();    int hash = spread(key.hashCode());    int binCount = 0;    for (Node
[] tab = table;;) { Node
f; int n, i, fh; K fk; V fv; if (tab == null || (n = tab.length) == 0) tab = initTable(); else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) { // 利用CAS去进行无锁线程安全操作,如果bin是空的 if (casTabAt(tab, i, null, new Node
(hash, key, value))) break; } else if ((fh = f.hash) == MOVED) tab = helpTransfer(tab, f); else if (onlyIfAbsent // 不加锁,进行检查 && fh == hash && ((fk = f.key) == key || (fk != null && key.equals(fk))) && (fv = f.val) != null) return fv; else { V oldVal = null; synchronized (f) { // 细粒度的同步修改操作... } } // Bin超过阈值,进行树化 if (binCount != 0) { if (binCount >= TREEIFY_THRESHOLD) treeifyBin(tab, i); if (oldVal != null) return oldVal; break; } } } addCount(1L, binCount); return null;}

小结

本节回答了java提供的并发容器分类,以及ConcurrentHashMap在java7,java8中的是如何保证线程安全的。
面试官喜欢问分离锁,画一下数据结构就明确了。

image.png

原创不易,转载请注明出处,让我们互通有无,共同进步,欢迎多沟通交流

你可能感兴趣的文章
用上帝之眼进行自动化测试
查看>>
为LoadRunner写一个lr_save_float函数
查看>>
PrefTest工作室全新力作-《性能测试与调优实战》课程视频即将上线
查看>>
质量度量分析与测试技术 培训大纲
查看>>
欢迎加入【亿能测试快讯】邮件列表!
查看>>
为什么我们的自动化测试“要”这么难
查看>>
LoadRunner性能脚本开发实战训练
查看>>
测试之途,前途?钱途?图何?
查看>>
adb常用命令
查看>>
通过LR监控Linux服务器性能
查看>>
通过FTP服务的winsockes录制脚本
查看>>
LRwinsocket协议测试AAA服务器
查看>>
Net远程管理实验
查看>>
反病毒专家谈虚拟机技术 面临两大技术难题
查看>>
几种典型的反病毒技术:特征码技术、覆盖法技术等
查看>>
Software Security Testing软件安全测试
查看>>
SQL注入漏洞全接触--进阶篇
查看>>
SQL注入漏洞全接触--高级篇
查看>>
SQL注入法攻击一日通
查看>>
论文浅尝 | 通过共享表示和结构化预测进行事件和事件时序关系的联合抽取
查看>>