谈一谈不常见却又不可少的ThreadLocal

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

在写ThreadLocal之前,需要先巩固下一点相关知识:Java内存模型及共享变量的可见性。

内存模型中所有变量存储在主内存中,当一个线程中要使用某个变量时,需要从主内存复制该变量到其线程内才能操作,此时线程中操作的是主内存变量的副本,操作完成后再刷回主内存。刷回的实质就是变量赋值

如果多个线程访问同一个变量时,每个线程都具有一个副本,操作完毕后都会刷回主内存,刷回时间存在先后,则赋值有先后,当然后者会覆盖前者,这是造成可见性问题的次要原因。

引入以上知识点后,再来说明ThreadLocal。一个线程想使用某个变量,于是从主内存复制该共享变量到线程内部中。使用完毕后想再下次再次使用该变量时,得到的变量副本是上次使用的副本,而不是从主内存的变量再次复制过来的副本,并且不想让其他线程影响到该变量。这就是ThreadLocal的目的,其实现不是通过共享变量这种方式实现的,详细内容下面介绍

目的很明确,但是身处JAVA内存模型中要遵循内存模型规范,下面看看JDK是如何即满足内存模型规范,又满足ThreadLocal目的。

满足内存模型

这点很简单,就是你该怎么样还怎么样,仍然受你管辖,该复制就复制,该刷回就刷回,不可见还是会造成不可见。

满足ThreadLocal目的

多个线程都能访问的变量才叫共享变量,如果控制变量的访问方式,使其他线程线程不能访问就可以了。控制方式就是将线程与变量的一一对应,将该变量的访问入口控制到只有该线程即可,JDK中的做法就是让线程持有这个变量(绑定到线程本身)

线程可以绑定变量,但是并不知道需要绑定多少个,于是将这个存储功能还是交给专门的数据结构—>Map。并且还专门设计了一个用来访问这个Map的工具,这个工具就是ThreadLocal。并且这个Map的key为ThreadLocal实例的引用地址,value存储真正的变量。

这样设计就到达目的了。ThreadLocal构建时接收个泛型告诉你存储的变量是一个对象类型。

 

ThreadLocal设计

核心Map设计

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;
        }
    }
...
}

这里Map的Entry被设计为弱引用。

内存存储图示如下

弱引用WeakReference

WeakReference是Java语言规范中为了区别直接的对象引用(程序中通过构造函数声明出来的对象引用)而定义的另外一种引用关系。WeakReference标志性的特点是:reference实例不会影响到被应用对象的GC回收行为(即只要对象被除WeakReference对象之外所有的对象解除引用后,该对象便可以被GC回收),只不过在被对象回收之后,reference实例想获得被应用的对象时程序会返回null。

这里使用弱引用的原因:ThreadLocal目的就是达到变量只能自己访问别的线程不能访问的目的,Map设计的key为ThreadLocal实例的引用地址,value为变量,当线程存在而ThreadLocal实例被回收时,Map中的value还是存在的(原因后续说明)致使该变量的可达性分析失败,从而导致此阶段的内存泄露。当设计为弱引用后,如果key被销毁了(强引用销毁),那么value就处于可被回收状态,从而避免内存泄露。

临时内存泄露图示

ThreadLocal实现原理,为什么内存泄漏,怎么解决的内存泄漏】 阅读详情

相关推荐

ThreadLocal为什么会内存泄漏?如何解决?

在这种情况下,父线程和子线程都会共享该值,容易导致泄漏,因此使用后也应及时清理。方法,即使线程结束,大量数据(50MB)也会被释放,可能会导致内存泄漏。(线程局部变量的值)仍然存在,而这个值无法被自动清理,因为。中的值,下一个任务复用同一个线程时,旧数据依然存在内存中。引发的内存泄漏问题,并确保系统的内存使用更加高效和安全。在线程池中,线程的生命周期通常较长,可能导致。,以减其生命周期范围,避免长时间的内存占用。时,线程通常是复用的。方法来手动清除当前线程的变量。的子类,它允许子线程继承父线程的。

hikktn的博客 1502

图文Debug详解 ThreadLocal内存泄漏的原因

一、前言 在分析ThreadLocal导致的内存泄露前,需要了解一下内存泄露、强引用与弱引用以及GC回收机制。这样才能更好分析ThreadLocal泄漏的原因。 如果了解上述问题可直接跳到第二节。 1.1 内存泄漏 如果会被使用的对象或者变量占用的内存能被回收,就是内存泄漏。如果泄漏的数据量足够大,可能会引起内存溢出,导致程序异常结束。 1.2 强引用与弱引用 强引用: 如 String name = new String(); 一个对象具有强引用,会被垃圾回收器回收。当内存空间足,Java虚拟机

qq_40205337的博客 5336

ThreadLocal内存泄漏原理解析

ThreadLocal内存泄漏原理解析

jack__love的博客 5236

ThreadLocal原理与内存泄漏

ThreadLocal原理以及ThreadLocal内存泄漏的原因分析

m0_63743928的博客 1691

谈一谈ThreadLocal的理解

什么是ThreadLocalThreadLocal提供一个线程的局部变量,访问某个线程拥有自己局部变量。当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而会影响其它线程所对应的副本。 ThreadLocal的作用 ThreadLocal的作用主要是做数据隔离,填充的数据只属于当前线程,变量的数据对别的线程而言是相对隔离的,在多线程环境下,可以防止自己的变量被其它线程篡改。 ThreadLocal的使用场景

weixin_43217065的博客 662

Java面试】谈一谈你对ThreadLocal的理解

每个线程都可以独立修改属于自己的副本而会互相影响,从而隔离了线程和线程. 避免了线程访问实例变量发生安全问题. 同时我们也能得出下面的结论:(1)ThreadLocal只是操作Thread中的ThreadLocalMap对象的集合;(2)ThreadLocalMap变量属于线程的内部属性,同的线程拥有完全同的ThreadLocalMap变量;(3)线程中的ThreadLocalMap变量的值是在ThreadLocal对象进行set或者get操作时创建的;

weixin_74412978的博客 1354

ThreadLocal 常见使用场景

ThreadLocal 之前一篇文章我已经和大家探讨了ThreadLocal的实现原理,并分析了源码,现在这篇文章带大家了解一下其常见的使用场景,在最近的项目中我也用到了。首先复习下其包含的四个方法: void set(Object value) // 设置当前线程的线程局部变量的值。 public Object get() // 该方法返回当前线程所对应的线程局部变量。 public void remove()// 将当前线程局部变量的值删除,其目的是为了减内存使用,加快内存回收。 protected

m0_61802230的博客 7514

谈一谈ThreadLocal

ThreadLocal是什么 如果某个变量只为单独线程服务,存在共享的场景,我们可以考虑将变量放在ThreadLocal里,ThreadLocal将变量和线程绑定。这样方便了使用,也规避了线程安全因素。 ThreadLocal怎么使用 /** * ThreadLocal存放数据 * 父子线程共享 */ public static void thr...

m0_46789507的博客 293

谈一谈JavaThreadLocal

谈一谈JavaThreadLocal

liuruiaaa的博客 986

线程中必不可ThreadLocal

ThreadLocal详解 (一)概述 通常情况下,我们创建的变量是可以被任何一个线程访问并修改的。如果想实现每一个线程都有自己的专属本地变量该如何解决呢? JDK中提供的ThreadLocal类正是为了解决这样的问题。 ThreadLocal类主要解决的就是让每个线程绑定自己的值,可以将ThreadLocal类形象的比喻成存放数据的盒子,盒子中可以存储每个线程的私有数据。 (二)基本使用 如果你创建了一个ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的本地副本,这也是ThreadLo

物是人非,结局始终不美 2169

常见知识点和易错点:一直都太明白的ThreadLocal

常见知识点和易错点系列三、简单捋捋ThreadLocal这玩意这玩意是什么?能干什么?学会使用ThreadLocal,先来过把瘾step1: 创建step2:设值、取值step3: 销毁完整Demo看看ThreadLocal核心源码两种创建方式,殊途同归?先调用了set(), 就会触发initialValue()?新朋友, ThreadLocalMap初次见面,揭开面纱敞开心扉,展示源码创建ThreadLocalMap取值、设值江湖再见,总结算上总结的总结 三、简单捋捋ThreadLocal这玩意 看了

5akura's Blog 471

ThreadPoolExecutor 与 ThreadLocal 配合使用中出现数据一致问题

ThreadPoolExecutor 与 ThreadLocal 配合使用中出现数据一致问题

java_magicsun的专栏 3492

ThreadLocal究竟存存在内存泄漏?

现在正是金三银四的春招高潮,前阵子小编一直在搭建自己的网站,并整理了全套的**【一线互联网大厂Java核心面试题库+解析】:包括Java基础、异常、集合、并发编程、JVM、Spring全家桶、MyBatis、Redis、数据库、中间件MQ、Dubbo、Linux、Tomcat、ZooKeeper、Netty等等**《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》

shenliba的博客 784

ThreadLocal常见使用场景

threadLocal常见常见,面试可用!

自救 唯有自强 815

ThreadLocal 香了?ScopedValue才是王道?

大家好,我是才陈某~ThreadLocal是一种实现将变量在各线程之间隔离的方案,也叫线程局部变量表。在Java中每个线程都拥有一个ThreadLocal下的ThreadLocalMap类型的变量,它用来存储定义在线程中的ThreadLocal对象,ThreadLocalMap的键是一个弱引用,指向对应的ThreadLocal对象。但值得每一位Java开发者注意的是ThreadLocal变量如果...

码猿技术专栏 693

ThreadLocal原理、ThreadLocal的使用、ThreadLocal内存泄漏、ThreadLocal的坑

文章目录背景说明一:ThreadLocal的原理1.1 什么是ThreadLocal变量1.2 ThreadLocal实现原理1.3 ThreadLocalMap实现原理1.4 ThreadLocalMap结构图二:ThreadLocal的使用2.1 创建ThreadLocal工具类2.2 在拦截器/过滤器中通过用户token获取登录信息,并与当前线程绑定2.3 业务处理时获取用户信息2.4 当前请求结束时,销毁ThreadLocal变量三:ThreadLocal的坑、ThreadLocal内存泄漏3.1

weixin_49114503的博客 8839
上一篇: 京东资深技术专家在线分享“微服务架构与实践”实战笔记!
下一篇: 阿里校招成功上岸分享,这份Java核心笔记建议收藏!
java架构师小芷
博客等级 码龄6年 216粉丝 519原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值