jackson实现的LRUMap(LinkedHashMap + ReentrantReadWriteLock)引起的死循环问题

jackson实现的LRUMap(LinkedHashMap + ReentrantReadWriteLock)引起的死循环问题

  1. 线上服无法登录,通过监控发现有几个逻辑cpu占用都到了100%
    • 和腾讯线上运维联系,确认Java下某个逻辑线程CPU占用一直占用100%,并确认了线程堆栈(top + jstack)
    • 确认线程堆栈是jackson#LRUMap.put#HashMap.resize#LinkedHashMap.transfer
    • 这是一个经典的hashmap#死循环问题
    • 但上述只有在并发条件下才会出现问题,但是LRUMap#put是用了ReentrantReadWriteLock#写锁,应该是单线程的
    • 原因#其根结在于LinkedHashMap的get()方法会改变数据链表
    • 参考
  2. 结合之前的issues
    • 看之前线上出问题的jstack
    • 发现所有的逻辑线程都阻塞在LRUMap.get,这是一个ReentrantReadWriteLock#读锁
    • 从读写锁原理来看,肯定是线程在持有写锁,结合刚才1的分析
    • 查看了一下堆栈,发现有逻辑线程在执行#LRUMap.put,触发死循环,从而一直持有写锁,这样其他逻辑都被阻塞了,卡住
    • 参考
  3. 解决
    • LinkedHashMap + ReentrantReadWriteLock 实现LRUCache是有性能问题的,一个写操作会锁住整个缓存,阻塞所有读操作
    • 其根结在于LinkedHashMap的get()方法会改变数据链表,结合读写锁(get),则会造成死循环
    • 升级了jackson的版本到2.9.8,并且阅读了源代码发现LRUMap实现不再继承LinkedHashMap,而是采用组合了ConcurrentHashMap,而且不再使用读写锁
    • jackson本身的相关issues
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容