[一句话讲清]ThreadLocal为什么会内存泄漏?

文章讨论了ThreadLocal在内存泄漏中的情况,当ThreadLocal对象未被remove且线程未销毁时,强引用可能导致内存泄漏。通过使用弱引用,ThreadLocalMap能更有效地清理不再使用的缓存,避免内存泄漏。
摘要由CSDN通过智能技术生成

[一句话版本]

如果ThreadLocal存了值,且在清除ThreadLocal之前未使用remove()方法清除值,那么这个存的值就找不到了,但是这个值还在被强ThreadLocalMap强引用,就发生了内存泄漏(一般在使用綫程池时问题较大,因为线程不会销毁,内存泄漏一直在)。
在这里插入图片描述

前置知识

  1. 一个对象被强引用时,垃圾回收器不会回收这个对象,即使系统内存不足也不会回收。只有当该对象的强引用被显式地释放,或者不再被任何引用关联时,该对象才会成为垃圾回收的候选对象,且回收条件是内存不够用了。
  2. 一个对象只被弱引用时,垃圾回收在内存够用时也会收走。四种引用
  3. 每个线程对象Thread都会强引用ThreaLocalMap(存ThreadLocal的数据用的)。
  4. ThreaLocalMap的Key弱引用ThreadLocal。

内存泄漏原因

假设:

现在有一个ThreadLocal对象tl2被销毁,那么tl2强引用的堆中的ThreadLocal对象也会在内存不够用时回收,自然地,该对象弱引用的key2(key就是一个ThreadLocal对象)也会被回收。
但是,当线程存在,也就是Thread还没被销毁时,Thread会强引用ThreaLocalMap,此时ThreaLocalMap中的key2被销毁了,但是其对应的value2还没被销毁,但是也招不到了,此时就泄漏了。

代码:

从下面代码可以看到key是被LocalMap弱引用的,而value是被强引用的。那么当外部不强引用key时,那么key就被回收,但value仍在localmap中。

static class ThreadLocalMap {
    static class Entry extends WeakReference<ThreadLocal<?>> {
        /** The value associated with this ThreadLocal. */
        Object value;

        Entry(ThreadLocal<?> k, Object v) {
            super(k);
            value = v;
        }
    }
    ...
   }
为什么key不用强引用?

如果为弱引用,当外部不用threadlocal时,key会自动被清理为null,后续再对threadlocal操作时可以顺带查找key为null的entry把value清理了。但是如果key为强引用,那么key就有值,后续就不知道这个key是否被外部引用,也就不能清理了。所以,总的来说,设为弱引用能够帮助我们更简单清理泄漏的缓存
更详细分析为什么这么设计

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值