ThreadLocal

链接
知乎

简书

首先明确threadlocal既然能够做到线程私有变量,直觉应该是他是一个map,key为线程,value为线程私有值,但是这种设计有一个问题,内存泄露,即使某线程已经结束了,那些数据也不会被清除。
所以才用了以下的设计,每个线程独有ThreadLocalMap,key为threadLocal,value为线程私有值,这样再来看一下上面那个问题,线程结束了,这个ThreadLocalMap没有引用了,会被GC回收
在这里插入图片描述
再来看看另一个问题,是不是threadlocal弱引用造成了内存泄露?

并不是,如果是强引用,那么其实线程中ThreadLocalRef引用断掉,那么ThreLocal也不会被回收,明明不要用这个ThreadLocal了,也不被清除是不合理的。
而使用若引用,只要从GCRoots不可达,那么作为key的ThreadLocal就会被删除,此时出现了,value还有引用,不会被清除的局面,所以需要在下一次ThreadLocalMap调用set(),get(),remove()方法的时候会被清除value值。

由于Thread中包含变量ThreadLocalMap,因此ThreadLocalMap与Thread的生命周期是一样长,如果都没有手动删除对应key,都会导致内存泄漏。
但是使用弱引用可以多一层保障:弱引用ThreadLocal不会内存泄漏,对应的value在下一次ThreadLocalMap调用set(),get(),remove()的时候会被清除。
因此,ThreadLocal内存泄漏的根源是:由于ThreadLocalMap的生命周期跟Thread一样长,如果没有手动删除对应key就会导致内存泄漏,而不是因为弱引用。

总结

牢记上面的图,关于引用的指向理解,从声明指向对象,在使用清除算法的时候,就是从GCRoots的图的遍历了,当某对象不可达时,就说明是可回收对象。
关于设计问题:从两个层面考虑:
第一个线程结束的时候,要把该线程对应的私有变量都回收了,所以采用每个线程私有Map的设计。
第二个当某个ThreadLocal不用的时候,我能主动释放,不能说某线程的map的key中还有该ThreadLocal的引用就不给我回收此ThreadLocal了,所以设计map的key对ThreadLocal的引用为弱引用。(要是设计为强引用,那ThreadLocal自己都不能回收了,更是内存泄露)但是这是这种霸道行为,导致了ThreadLocal的key指向null了,也造成了自己的内存泄露,那你就自己解决吧,下次调用set(),get(),remove()方法的时候会被清除value值,反正我不用这个ThreadLocal了。
两个结束,线程结束,map回收,ThreadLocal结束了不用了可以回收

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值