“ThreadLocal内部的ThreadLocalMap键为弱引用,会有内存泄漏的风险” 真的是这样吗?

之前的一个评论,博主把文章删除了。

ThreadLocal内部的ThreadLocalMap键为弱引用,会有内存泄漏的风险,真的是这样吗?

我认为不太合理。原因是:

  1. ThreadLocalMap中的Entry弱引用(key)到的是 threadLocal 对象,
    此处的弱引用意图是,当外界不再持有对 threadLocal 对象的强引用的时候,
    threadLocal 对象可以被GC。此处Entry对 threadLocal 的弱引用不会引起内存泄露。

  2. Entry除了持有对threadLocal的弱引用之外还持有对value的强引用。
    先说为什么调用了threadLocal.remove() 就解决了内存泄漏的风险。
    threadLocal.remove() 这个方法最终会有机会执行到:
    entry.value = null;
    entry = null;
    这样就解除了entry对value的强引用关系,当外部也没有对value的强引用的时候,
    value就可以被GC。

如果不调用threadLocal.remove() 这个方法,其实也是要分情况来考虑的。
我们知道 entry 是被 threadLocalMap 引用的;而 threadLocalMap 是被 thread 引用的。
如果一个thread执行完毕,进入 TERMINATED 状态时,作为一种GC Root,
terminated 状态的 thread本身就是可以被GC的。
那么thread所引用的 threadLocalMap 也就是可以被GC的。

那么什么情况下 threadLocalMap 不能被回收呢?
那就是thread并不会进入 terminated 状态的时候。
什么时候不进入 terminated 呢?就是当 thread 配合线程池使用的情况下,thread在运行完毕之后
会被再次放回线程池。
那么如果这个线程永远不被用到,此处的threadLocalMap 包括entry 和 entry引用的value 就不能被回收了。
那么如果这个线程被再次启用,那么threadLocalMap也就不会再重新初始化了。
此处应该考虑另外一个问题,那就是如果再次调用 threadLocal.get() 方法,得到的是上一次set的内容,
也就是脏读了。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容