ThreadLocal

ThreadLocal类用来提供线程内部的局部变量

ThreadLocal实例 通常来说都是private static类型的,用于关联线程和线程上下文

ThreadLocal与synchronized的区别

synchronized:同步机制采用'以时间换空间'的 方式, 只提供了一份变量,让不同 的线程排队访问;侧重于多个线程之间访问资源的同步

ThreadLocal采用'以空间换时 间'的方式, 为每一个线程都提供 了一份变量的副本,从而实现同 时访问而相不干扰;侧重于多线程中让每个线程之间的数据 相互隔离。

数据结构

每个Thread中都具备一个ThreadLocalMap,而ThreadLocalMap可以存储以ThreadLocal为 key ,Object 对象为 value 的键值对。

ThreadLocal与内存泄漏

相关概念

Memory overflow:内存溢出,没有足够的内存提供申请者使用。

Memory leak: 内存泄漏是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪 费,导致程序运行速度减慢甚至系统崩溃等严重后果。内存泄漏的堆积终将导致内存溢出。

强引用(“Strong” Reference),就是我们最常见的普通对象引用,只要还有强引用指向一个对象, 就能表明对象还“活着”,垃圾回收器就不会回收这种对象。

弱引用(WeakReference),垃圾回收器一旦发现了只具有弱引用的对象,不管当前内存空间足够与 否,都会回收它的内存。

产生原因

static class Entry extends WeakReference<ThreadLocal<?>> {
    Object value;

    Entry(ThreadLocal<?> k, Object v) {
        super(k);
        value = v;
    }
}

ThreadLocalMap 的 key 和 value 引用机制:

  • key 是弱引用ThreadLocalMap 中的 key 是 ThreadLocal 的弱引用 (WeakReference<ThreadLocal<?>>)。 这意味着,如果 ThreadLocal 实例不再被任何强引用指向,垃圾回收器会在下次 GC 时回收该实例,导致 ThreadLocalMap 中对应的 key 变为 null
  • value 是强引用:即使 key 被 GC 回收,value 仍然被 ThreadLocalMap.Entry 强引用存在,无法被 GC 回收。

当 ThreadLocal 实例失去强引用后,其对应的 value 仍然存在于 ThreadLocalMap 中,因为 Entry 对象强引用了它。如果线程持续存活(例如线程池中的线程),ThreadLocalMap 也会一直存在,导致 key 为 null 的 entry 无法被垃圾回收,即会造成内存泄漏。

也就是说,内存泄漏的发生需要同时满足两个条件:

  1. ThreadLocal 实例不再被强引用;
  2. 线程持续存活,导致 ThreadLocalMap 长期存在。

为什么必须使用弱引用

如果 ThreadLocal 对线程本地变量(ThreadLocalMap)使用强引用,那么当 ThreadLocal 对象不再被外部引用时,由于 ThreadLocalMap 仍然被线程持有强引用,垃圾回收器无法回收 ThreadLocal 对象,从而可能导致内存泄漏。因为线程的生命周期可能很长,大量的无法被回收的 ThreadLocal 对象会占用内存空间

避免措施

remove()

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值