欧博平台注册
热门标签

彩票现金网网站安全警告_高并发办事优化篇:详解一次由读写锁引起的内存袒露

时间:2023-10-30 08:07    点击次数:114
据报道,某地区的一家赌场近期开放了新的游戏模式,吸引了众多玩家的参与。该模式采用了最先进的技术和设备,让游戏体验更加刺激和有趣,同时也为赌场带来了更多的收益。彩票现金网网站安全警告

[[414812]]太阳城网

JVM关联的极度,一直是一线研发比拟头疼的问题。因为关于业务代码,JVM的运行基本算是黑盒,当极度发生时,较难直不雅的看到和找到问题方位,这亦然咱们一直要接洽其里面逻辑的原因。

本篇就由一个近期线上JVM内存袒露的例子,带公共强行分析一波~

网站安全警告 Part1 线上办事器报警了

某天,共事来找我襄理,蓝本是某系统毫无征兆的来了一连串报警,一波机器的老年代内存占用率教悔阈值~

www.hg86r.com

1.1先看进展

老年代内存占用

不错看到,在7月中旬之前,内存占用照旧比拟浅近的,每次GC皆不错回收掉很大一部分的老年代对象。

而中旬之后,老年代内存一直冉冉增长而无法开释。很昭着,应该是对象没法被浅近回收导致。

内存袒露了~

1.2 怎样办呢

如若是刚上线的时势爆出了此类问题,因为影响面比拟小,不错径直先回滚代码,止血为第一要务。

welcome诚博手机版app

不外,这个时势昭着依然上线N多天,中间还不知谈上过些许需求,况兼,既然流量近期有上升导致问题出现,阐发,依然对客开流量了。

回滚是不成能了,执紧时刻定位问题,上线配置吧。

Part2 定位问题

一般的体式:

拿到dump文献 用MAT等用具,找出内存占用过多的极度对象,以及援用研究 分析极度对象关联代码的可能问题

不外,因为此次dump下来的文献十多G,太大的,MAT基本窝囊为力,只可打印出来东谈主工分析了

2.1 定位问题代码

皇冠体育hg86a

jmap效用稽查

很庆幸,极度对象相称昭着。Point对象和GeoDispLocal对象,尽然多达好几百万实例数,那就先看下代码中这两个对象是怎样用的。

private 太阳城网static final CacheMap<String, List<GeoDispLocal>> NEAR_DISTRICT_CACHE = new CacheMap<String, List<GeoDispLocal>>(3600 * 1000, 1000);  private static final CacheMap<Integer, Point> LOCAL_POINT_CACHE = new CacheMap<Integer, Point>(3600 * 1000, 6000); 

皆是被存放在本次缓存CacheMap中(内存袒露的一个常宥恕因,便是因为被静态汇注持有,无法回收导致),而dump文献中的CacheMap.Entry也长短常高的。

CacheMap便是咱们的第一优先怀疑对象了。先看下这个缓存类是怎样回事:

ublic class CacheMap<K, V> {     private final long expireMs;     private LRUMap<K, CacheMap.Entry<V>> valueMap;     //其他略 } 

里面依赖一个带LRU功能的map,怎样达成的呢:

public class LRUMap<K, V> extends LinkedHashMap<K, V> {     private static final long serialVersionUID = 1L;     private final int maxCapacity;     // 这个map不会扩容     private static final float LOAD_FACTOR = 0.99f;     private final ReadWriteLock lock = new ReentrantReadWriteLock();      public LRUMap(int maxCapacity) {         super(maxCapacity, LOAD_FACTOR, true);         this.maxCapacity = maxCapacity;     }      @Override     protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {         return size() > maxCapacity;     }      @Override     public V get(Object key) {         try {             lock.readLock().lock();             return super.get(key);         } finally {             lock.readLock().unlock();         }     }      @Override     public V put(K key, V value) {         try {             lock.writeLock().lock();             return super.put(key, value);         } finally {             lock.writeLock().unlock();         }     }     //remove clear 略 } 

里面是一个依赖LinkedHashMap达成的LRU缓存。看慎重,商量是要构建一个摈弃容量、且不会进行扩容的MAP(百度了一波,和网上的达成一模同样~)。那么,骨子情况真的和思象中的同样么?。

2.2 LinkedHashMap达成的LRUMap好使么

银河娱乐app是国外的吗

咱们来看容量和扩容关联的诞生:为什么筹商者合计该LRUMap不会进行扩容?

//**把容量和扩容关联的参数摘出来** //用户祈望的最大容量 private final int maxCapacity; //加载总共 private static final float LOAD_FACTOR = 0.99f; //构造函数中调用LinkedHashMap进走运行化 super(maxCapacity, LOAD_FACTOR, true);  @Override  //复写删除最久元素条目要领 protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {    //当LinkedHashMap.size 比 咱们摈弃容量大时,实行删除    return size() > maxCapacity; } 

按咱们的骨子使用实例化一下:

maxCapacity=6000,是咱们但愿的最大元素容量。 load_factor=0.99 加载因子。 Map里面threshold=8192*0.99=8110,是那么下次扩容时的容量大小。(map中table容量的真的大小是离6000最近的2的N次幂,即8192)。

因为复写了LRU条目函数,当size>6000时会进行LRU替换。因此,表面上,size耐久不会达到8110。

怎样贬责并发下的读写碎裂呢?

皇冠博彩公司

皇冠客服飞机:@seo3687

//读写锁 private final ReadWriteLock lock = new ReentrantReadWriteLock();   public V get(Object key) {    try {        lock.readLock().lock();        return super.get(key);    } finally {        lock.readLock().unlock();    } }  public V put(K key, V value) {    try {       lock.writeLock().lock();       return super.put(key, value);    } finally {       lock.writeLock().unlock();    } } 

筹商者为了贬责并发下的读写碎裂,给查询和修改要领加了锁,为了兼顾性能,使用了读写锁:在get的时候加读锁,在put/remove的时候加写锁。

看起来,总共这个词筹商很好的贬责了LRUMap的固定容量和并发操作问题,那么事实是什么样的呢?

其实,这个问题很早就有东谈主分析过了[1] ,是因为LinkedHashMap在get读操作的时候,会为了爱戴LRU从而进行元素修改,行将get到的元素升沉到链表终末。这么,就导致了读写并提问题,但这个阐发注解嗅觉朦邋遢胧,因此,我决定在其基础上对读写并提问题再讲精致一些。

2.3 LinkedHashMap内存袒露拆解

皆加了读写锁为什么不好使呢?

深度

这里咱们照旧需要先明确,读写锁的见地和适用场景:读写锁,允好多个线程分享读锁,适用于读多写少的情况。(前提是,读操作不会改革存储结构)

是以,问题就发生在get操作上,LinkedHashMap的get操作被重写,商量是为了达成LRU功能,在get之后,将现时节点挪动到链表终末。

挪动啊,同道们,这昭着是一个写操作,是以,加读锁还灵验么?

即允好多线程插足,又进行了修改,那还能起什么作用,能莫得并提问题么?

底下,对照节点挪动的代码,详备拆解一下多线程下的并提问题:

get之后的节点挪动,将节点挪动到终末

彩票现金网

骨子拆解分析如下,为什么在多线程的情况下,会出现内存袒露:

时刻片下多线程的get实行

咱们看到,在线程1实行完前两句,让出了时刻片,当线程2实行到p.after=null之后又出让了时刻片,这么,本来a应该是背面的<2,B>节点,效用多线程下变成了null,最终,背面两个节点被踢出了链表,删除操作无法触达,形成内存袒露。

考证的代码就不贴了,公共有酷好不错我方试一下~

皇冠博彩网址 Part3 总结

话说追溯,既然定位到了问题,这个内存袒露怎样配置呢?

体彩排列三历年第153期开出奖号分别为:866、950、181、666、698、006、629、383、270、308、088、622、885、083、060、066、368、155。统计详见下表:

首位号码:上期为:3,重号,走势活跃,冷码近期出现较少,本期防冷码回补,关注9。

zh皇冠客服真的假的

不错把读写锁改成互斥锁。大约径直用散播式存储,能慢些许呢,是不是,既浅易,毛糙,又免得为了从简机器内存我方构造LRUMap。 

每一个八股文皆不仅仅为了口试,而是每次线上问题排查的基石。千万别把八股文的作用定位错了。。。

本文转载自微信公众号「Coder的时刻之路  」,不错通过以下二维码关心。转载本文请研究Coder的时刻之路公众号。

 



上一篇:开云百家乐博彩篮球(www.kingofbetszonehomehub.com)
下一篇:欧博体育博彩网址博彩平台注册送红利 | “我愿将资质带到金州”! 骁雄国王完成3换1走动, 小萨示好库里!

网友评论