铜仁市论坛

首页 » 分类 » 灌水 » 高并发你敢信HashMap竟然干掉了
TUhjnbcbe - 2020/6/5 17:51:00
看白癜风的医院哪里好问题分析

RaceCondition(也叫做资源竞争),是多线程编程中比较头疼的问题。特别是Java多线程模型当中,经常会因为多个线程同时访问相同的共享数据,而造成数据的不一致性。为了解决这个问题,通常来说需要加上同步标志“synchronized”,来保证数据的串行访问。但是“synchronized”是个性能杀手,过多的使用会导致性能下降,特别是扩展性下降,使得你的系统不能使用多个CPU资源。

那是一个电商系统,运行在我们的T服务器(8核32线程)上。当个并发用户的时候居然把所有的CPU都压得满满的(90%以上的忙碌,甚至达到了%)。这是很少有的现象,在我测试的所有项目中很少有扩展性这么好的系统能把T的32个线程都占满的。我狠狠的夸了他们的应用。话音没落,却发现测试结果很差,平均响应时间很长。不可能呀,所有的CPU都在干活,而且都在用户态(如果在系统态干太多的活就有问题了),结果怎么还会差呢。CPU都在干嘛呢?

通过工具发现(DtraceforJava),我们发现很多的CPU都在做一件事情,那就是不停的执行一条Java语句(HashMap.get())。象是进入了死循环。我们进行了进一步试验,让并发用户数量为1,不停的运行10分钟,结果没有发现这种情况;接着我们让50个并发用户同时运行,但是只运行在一个CPU上(通过psrset),结果也没有出现死循环状态。只要并发用户数量超过10个,运行的CPU超过两个,不到2分钟就出现死循环。一旦死循环出现,大量CPU资源被白白浪费,性能自然很差。

源码分析

通过上面的试验我们可以很肯定的判断,是由于并发控制不好,导致数据的不一致,引起的死循环。值得一提的是,HashMap不是一个线程安全的数据结构,要用到多个线程中去,需要自己加上同步标志,为什么会死循环呢,看看下面HashMap中get函数的源代码:

publicVget(Objectkey){if(key==null)returngetForNullKey();inthash=hash(key.hashCode());for(EntryK,Ve=table[indexFor(hash,table.length)];e!=null;e=e.next){Objectk;if(e.hash==hash((k=e.key)==key

key.equals(k)))returne.value;}returnnull;}

get函数会根据key的hashcode来锁定多个对象,并且遍历这些对象来找到key所对应的对象。当多个线程不安全的修改HanshMap数据结构的时候,有可能使得这个函数进入死循环。

后来,我们使用ConcurrentHashMap或在使用HanshMap的时候加上同步标志,问题得到解决!

写在最后

最后,附上并发编程需要掌握的核心技能知识图,祝大家在学习并发编程时,少走弯路

特别推荐一个分享架构+算法的优质内容,还没

1
查看完整版本: 高并发你敢信HashMap竟然干掉了