通过一次线上case深入认识 ThreadLocal

前言

通过一次线上故障深入了解一下ThreadLocal, 以及相关的其他知识。

ThreadLocal的介绍

在每个线程Thread内部有一个ThreadLocal.ThreadLocalMap类型的成员变量threadLocals,这个threadLocals就是用来存储实际的变量副本的,键值为当前ThreadLocal变量,value为变量副本(即T类型的变量)。 初始时,在Thread里面,threadLocals为空,当通过ThreadLocal变量调用get()方法或者set()方法,就会对Thread类中的threadLocals进行初始化,并且以当前ThreadLocal变量为键值,以ThreadLocal要保存的副本变量为value,存到threadLocals。 然后在当前线程里面,如果要使用副本变量,就可以通过get方法在threadLocals里面查找。
什么地方用ThreadLocal呢?

  1. 记录当前线程的一些资源,把一些全局的变量存起来,当前线程使用。
  2. 分布式锁的可重入锁。

一: 匪夷所思的线上故障

项目介绍

项目主要有两个ThreadLocal, okData 和 errData, 分别存放校验通过的数据和异常的数据,主要流程,举例添加10个商品数据。

在这里插入图片描述

奇怪的异常信息

现在的异常是。用户只添加了一个商品,提示异常,但是实际商品列表确添加成功,非常奇怪。okData和errData里面怎么会出现都值的情况,而且在异常参数转化时报了异常。
在这里插入图片描述
这个异常的信息跟商品完全没关系,这个是怎么导致的呢。

排查流程。

1、一开始是任务代码逻辑异常,查看所有与app相关的信息,发现没有错误。
2、尝试复现,将出错用户的所有信息同步到线下,执行同样的操作均无法发现。
3、突然想起可能是上一个用到该线程的存储的信息。
在这里插入图片描述
4、果然,查看出错请求的同一个线程号的日志,发现上一个请求是get请求。未用到ThradLocal, 前二个请求是修改操作,用到errData ,且请求有问题。错误信息正好对应了app信息。

5.终于抓到了凶手,ThreadLocal 不规范使用导致的。整个项目是在每个接口执行的finally里面调用ThreadLocal 的remove()方法,释放掉数据, 虽然只是简单的几句话,但是排查起来还是很费力的。

6.后面肯定是处理了,这个应该通过aop在切面统一处理。

深入研究ThreadLocal。

首先了解一下Threadlocal的基础:
一个Thread中只有一个ThreadLocalMap,一个ThreadLocalMap中可以有多个ThreadLocal对象,其中一个ThreadLocal对象对应一个ThreadLocalMap中的一个Entry(也就是说:一个Thread可以依附有多个ThreadLocal对象)。通过源码发现ThreadLocalMap的Entry 的key就是ThreadLocal对象,value是值,其中有个地方我发现有点奇怪,为什么ThreadLocalMap使用弱引用呢。
在这里插入图片描述

先了解些弱引用

中所周知,JVM 进行GC的时候,会把无引用的内存对象给回收。弱引用就是如果一个内存对象只有弱引用,也会被回收,自己来测试一下。
声明一个弱引用A 和 强引用B
弱引用A

强引用B
解释下: people内存对象只有弱引用的时候,gc会回收,导致弱引用指向null.

看看ThreadLocal里面的弱引用。

如果ThreadLocal 对象置为null,由于仅有ThreadLocalMap 中Entry 的key的弱引用。此时gc的时候, key会变成null. 由于Threadlcoal 的get()/ set() 以及table的resize()方法里均有处理,以get()为例说明 里面有
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里会针对所有key未null的脏entry进行清理。可以实战一下

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值