ThreadLocal的内存泄漏分析
本文更新于:2020年2月5日。
声明:
关于 ThreadLocal 的内容介绍,现已汇总成一个系列,读完下面内容可以移步到这个网站:http://www.threadlocal.cn/
前言:
最近发了一篇文章,关于threadlocal内存泄漏的,收藏量挺大的,不过我个人感觉还有些地方可以阐述地更一针见血,所以又重新修订了一版,欢迎大家收藏。
本文的阅读方法
通常情况下,人们对threadlocal的理解思路是这样的:首先把它放在线程这个大的背景下去琢磨,然后认为它是解决多线程的变量冲突问题。
但是按照这样的思路去学习,其实效果不好。由于"线程"这个东西是抽象的东西,对于所有的人来说,"线程"就是一只拦路虎,让每一个接触ThreadLocal的人都产生了内心的抵触,产生了虚无缥缈的无助感,所以我们对ThreadLocal的理解没有深度,没有灵性,很教条,很空洞。
何不抛开线程而从变量的角度来认识和掌握 ThreadLocal呢?毕竟threadlocal是由两个维度组成:线程和变量。所以,阅读本文之前先抛开线程这个东西,单单从变量这个角度切入。
以变量角度切入threadlocal,等到了一定程度再顺手串联thread,所以本文的整体思路是:变量->线程。而不是:线程->变量。
1、threadlocal的变量属性
抛开线程的属性,threadlocal就是一种类型的变量而已。对于普通的变量而言,我们很熟悉,其操作过程无非就是这样的:
int a; //定义变量,开辟一块内存
a = 10; //给变量赋值
如上代码所示,整数字面量10存储到了变量a里面。a表示一块内存。当a不再被使用的时候,会被Java虚拟机所回收。
对于同样是变量的threadlocal而言,它的用法是这样的:
//声明一个threadlocal变量b,此时开辟了一块内存,里面存放的b对象
ThreadLocal<Integer> b = new ThreadLocal<Integer>();
//注意,这里不是赋值,赋值是=操作符
b.set(10)
在上面这个代码里面,10是放在了b里面吗?这一点令人非常的困惑!一定要记住牢记下面两点:
(1)10不是放在了b里面,10和b是两个独立存放的东西,不是包含关系。
(2)10和b是两个独立存放的变量,如果其中的一个被清理,那么另外一个不受影响的。
既然10和b是独立存放的,那么它们之间到底有什么关系呢?其实,这种关系,可以通过一个小故事来阐述清楚:
在抗日时期,有两名地下党A和B,A是上线,B是下线,B不能直接联系党中央的,他需要通过A来帮忙传话。一旦A发生意外,党中央就找不到B了,B一直存在,但是茫茫人海,党中央是无法启用B做战斗任务的安排,这种情况类似内存泄漏。
2、存放在哪里?
如上代码所示,10和b存放在哪里呢?线程活着,都有一个map,类似于context,每个线程都有一个map,随时随地可以存放东西。既然是map,肯定是用key-value的形式存在,key就是b,value就是10。
3、薄命郎:弱引用
10和b两个的独立存放的东西,只不过我们不能直接访问到10,必须通过b来传话,原因很简单,在map里面,value要通过key来访问。
不过,此时b被包装成了弱引用,也就是说它被打了一个标签,这样它很容易被gc。一旦b被清理了,10就找不到了,从而造成了内存泄漏。
总之,b是个薄命郎,用他来做上线,他很容易挂掉的。上线挂了,下线自然就联系不上了。
4、小结
(1)有两个变量a和b,如果后面不再参与计算,则会被自动回收;
(2)有两个变量a和b,存放在map里面,a是key,b是value。如果map一直存在,a和b因为被map关联,则a和b就一直不能被回收;
备注:线程活着,都有map,类似于context,每个线程都有一个map,好比一个context一样,随时随地可以存放东西
(3)有两个变量a和b,存放在map里面,a是key(但是a被弱引用包装了一下),b是value。如果map一直存在,a和b因为被map关联,则b就一直不能被回收,但是a可以被回收。一旦a回收了,那么无法通过a找到b了,这就是b出现内存泄漏。
5、公众号
如果诸位从这篇文章读到了收获,恭喜您!欢迎关注网站的公众号:
如果有内存泄漏的问题,我看mybatis中这个类 TransactionSynchronizationManager,中使用了很多的ThreadLocal变量,那么mybatis是否会有内存泄漏的问题吗?
首先纠正一点:TransactionSynchronizationManager,这个类不是mybatis的,是spring框架的。接着,我回答你的问题:不会造成内存泄漏,原因是其内的变量都是被static final所修饰。如果你对threadlocal不甚明了,请仔细阅读:http://www.threadlocal.cn/,第四节,第五节。