「图解」ThreadLocal 在并发问题中的应用

瑞萨RX USB驱动开发:从双模架构到RTOS集成的实战指南 USB(通用串行总线)作为现代嵌入式设备与主机通信的核心接口,其协议栈的复杂性常令开发者望而却步。其工作原理基于主机-从机架构和分层的描述符机制,通过控制、中断、批量与同步四种传输类型满足不同实时性与带宽需求。在嵌入式领域,高效、稳定的USB驱动价值在于显著降低开发门槛,加速产品上市,并确保工业控制、消费电子等场景下数据通信的可靠性。瑞萨电子的USB Basic Mini Host and Peripheral Driver,基于固件集成技术(FIT),正是为此而生。该驱动以轻量、可裁剪的‘迷你’设计,同时 阅读详情

前言

到底什么是线程的不安全?为什么会存在线程的不安全?线程的不安全其实就是多个线程并发的去操作同一共享变量没用做同步所产生意料之外的结果。那是如何体现出来的呢?我们看下面的一个非常经典的例子:两个操作员同时操作同一个银行账户,A操作员存钱,100B操作员取钱50。我们看一下流程。

两个操作员同时处理,没用做同步这个时候我们发现银行账户最终余额剩余950元,在我们想的最终结果银行账户应该剩余1000+100-50=1050元,在执行过程中我们没有加锁,最终导致了运行结果偏离预期。那么如何解决的?一般的解决措施就是加锁,加同步锁所以这就需要使用者一定要知道锁是什么。我们来看一下加锁之后的效果是不是我们所预期的。

在添加同步锁后我们可以看到,A操作员和B操作员同时去操作账户,但是A先抢占到资源,所以B就只能等待A操作员释放锁才能去操作银行账户,那么最终结果是我们所预期的吗?答案是的。 同步的话一般都是加锁,如果现在我想创建多个线程每个线程都是访问的自己的变量呢?各个线程之间毫无关联?
答案是有的。

ThreadLocal问题

ThreadLocal是JDK提供的,它提供了线程本地变量。什么是线程本地变量呢?其实就是你创建了一个Threadlocal变量,每个访问Threadlocal变量的线程都有一个本地副本。我们看下面的图:

从上面看出你创建一个ThreadLocal变量,每个访问该的线程都会复制到自己的本地,所以线程操作的都是本地的副本,这也就是说每个线程都是操作的自己本地的变量,那就完美的避免了线程安全的问题。

在这里还有一个问题。我在写这篇文章的时候看过很多文章,总的来说就是ThreadLocal就是为了解决多线程并发问题而提供的一种方法,还有一种解释就是ThreadLocal的最终目的就是为了解决多线程访问共享资源所产生的。真的对吗?ThreadLocal并没有共享那么从何而来的同步呢?

自己的想法

在看了Java并发编程之美后我所理解的Threadlocal提供了线程本地变量的副本,每个线程实际操作的是自己本地的变量副本,也就是说该变量副本只能当前线程访问,就不存在多个线程共享的问题,从Threadlocal名字我们也能看出本地线程。那那那它也就不存在去解决并发问题了。

如何使用

我们来看下面的例子。

输出结果:
Thread[Thread-1,5,main]====57
Thread[Thread-0,5,main]====75

创建了两个线程,它们都在threadlocal上面都set了一个随机数,我们看最后的输出结果每个都是不同的值,那么我们如果把threadlocal替换成一个集合会发生什么,由于两个线程时上个线程生成的随机数57会被第二个线程覆盖掉,而在Threadlocal中两个线程都是操作的自己的本地副本,那么两个线程互不影响都无法操控到对方的数据,因此它们存取的都是不同的值。

实现原理

那么Threadlocal是如何实现的呢?在研究Threadlocal的实现原理我们先看一下Thread的内部属性。

  • threadLocals 此线程保存的Threadlocal的值

inheritableThreadLocals等到后面再说。

在Thread的内部属性中我们看到了这两个默认为null的属性,threadLocals用来保存Threadlocal的本地副本,默认是为null只有调用Threadlocal的set时才会创建。也就是说Threadlocal就类似一个工具,它的作用就是把value的值通过set存在线程每个线程的threadLocals 中,只要线程一直存在threadLocals 也就一直存在。所以当不需要使用本地变量的时候可以调用Threadlocal的remove来清空本地变量。而threadLocals 为什么继承于ThreadLocalMap呢?ThreadLocalMap是一个定制的HashMap,而使用Map的原因就是可以每个线程关联多个Threadlocal变量。

set方法

我们来看一下set方法是如何实现的。

​

可以看出流程非常简单,首先获取当前线程然后在进行下一步操作,我们在看一下getMap做了什么

getMap主要就是返回了当前threadLocals的属性。那如果map为空呢?

如果map为空的话就直接创建一个新的ThreadLocalMap。

我们来看一下流程图。

get方法

看一下Get方法

首先根据当前线程获取实例如果存在就返回,如果不存在就先初始化一个空值,然后判断如果当前threadLoacals不为空就直接set一个空,否则就创建一个变量。

remove方法

remove方法相对来说比较简单。

总结

Threadlocal的实现原理其实就是通过set把value set到线程的threadlocals属性中,threadlocals类型是Map其中的Key就是Threadlocal的this引用,value就是我们所set的值,如果当前线程不销毁的话threadlocals会一直存在。一直存在的话可能会造成内存溢出,所以使用完之后尽量remove一下。不过在这里又有一个问题那就是如果我的线程想要读取主线程的变量要怎么做?我们上面的例子都是设置的新创建的线程,那么现在我在主线程中set一个值,这个时候我在新创建的线程中可以读取到吗?答案是不可以,因为Threadlocal不支持继承性。

我们看下面的例子:

输出结果:
Thread[Thread-0,5,main]====null

也就是说Threadlocal不支持继承性,主线程设置了值,在子线程中是获取不到的。那我现在想要获取主线程里面的值要怎么做?

Threadlocal是实现不了的,不过Threadlocal有一个子类可以实现。InheritableThreadLocal,InheritableThreadLocal是Threadlocal的实现,我们来看一个简单的例子。

输出结果:
Thread[Thread-0,5,main]====1000

运行结果发现子线程是可以获取到主线程设置的值的,那它是如何实现的?

我们看一下代码实现:

InheritableThreadLocal是继承Threadlocal的,并且把threadlocals给替换成inheritableThreadLocals了,所以上面的inheritableThreadLocals我要留在最后说,那么替换成inheritableThreadLocals后子线程就可以获取到主线程设置的属性了吗?我们在看一下Thread的实现。

看Thread的初始化方法可以看出,先获取了当前线程(主线程)判断主线程的inheritableThreadLocals不为空的话就调用createInheritedMap方法赋值给子线程中的inheritableThreadLocals。

配置VS Code使用Linux服务器上的Matlab 0、需求 Linux服务器上安装有Matlab 无图形界面,只能使用命令行工具,编辑文件不方便 1、VS Code插件安装 在扩展商店中搜索matlab,会出现Matlab Extension Pack,里面有整理好的matlab扩展 这里只安装了第一排的三个扩展 2、设置(Windows、Mac的设置类似,只是不同系统的文件路径不同) 安装好扩展,重启VS Code后,进行设置 打开:文件→首选项→设置(或快捷键ctrl+,),搜索matlab,结果如下图所示;直接打开完整json配置文件(图 阅读详情

相关推荐

Isaac Sim 6 利用Replicator实现高效语义分割与实例分割(实践指南5.10)

本文详细介绍了如何利用Isaac Sim 6的Replicator工具高效生成语义分割和实例分割数据集。通过虚拟环境自动标注,效率提升20倍以上,特别适用于农业机器人等计算机视觉项目。文章包含环境配置、场景构建、批量标注技巧及实例分割处理等实战指南,帮助开发者快速掌握合成数据生成技术。

weixin_42526415的博客 267

Java并发工具之ThreadLocal

ThreadLocal 字面意思是本地线程,其实更准确来说是线程局部变量,线程类 Thread 有个变量叫做 threadLocals,其类型就是ThreadLocal.ThreadLocalMap 类型,他其实不是一个 Map 类型,但可以暂时理解它是一个Map,键为 ThreadLocal 对象,值就是要存入的value。

Qynwang的博客 6544

放弃FFT全频计算!在STM32F407上用DFT单点计算提速50%的优化技巧

本文详细介绍了在STM32F407上通过DFT单点计算实现比FFT快50%的优化技巧,特别适用于生物阻抗分析、振动监测等只需关注单一频点的嵌入式场景。通过预计算相位角、查表法和混合精度计算等策略,显著提升计算效率和内存利用率,同时保持高精度。

weixin_28738397的博客 195

Java多并发(三)| 线程间的通信(ThreadLoacl详解)

Runnable:Running和Ready的合并几个方法的比较:初始化线程: 开启线程的四种方式: 实现Runnable接口 实现Callable接口+FutureTask(可以拿到返回结果,可以处理异常) 线程池(以后的章节会详解) 四种方式的对比:理解中断:volatile关键字的通信:synchronized的通信(同步方法、代码块):Lock接口的各种锁: 原子变量: 结果分析 调用过程图示 细节:等待队列和同步队列的线程被notify通知后的行为:...

光看不点赞的博客 855

MavLink协议入门

MAVLink是一个非常轻量化的开源的消息协议,用于无人机之间的通信以及无人机机载设备之间的通信。

ffffffeiyu的博客 2478

音频DSP开发中的‘隐藏关卡’:那些SigmaStudio未公开的模块计算秘籍

本文深入探讨音频DSP开发中SigmaStudio未公开的模块计算秘籍,重点解析动态范围控制、均衡器参数映射和混响算法优化等核心模块计算公式。通过实际案例揭示如何利用这些非官方技巧提升音频质量与系统性能,为ADI DSP开发者提供宝贵的实战经验。

water的专栏 911

ThreadLocal

1. ThreadLocal源码分析 2. JDK1.7、JDK1.8的差异 3. ThreadLocalRandom 4. InheritableThreadLocal 5. ThreadLocal的内存泄漏

weixin_45683550的博客 323

Emuelec系统安装全流程:超详细版指南(从零开始)

手把手带你完成emuelec系统的完整安装,从基础准备到系统配置一步不落,适合新手入门。深入解析emuelec在各类设备上的部署技巧,让复古游戏体验更流畅。

weixin_42594419的博客 1974

浅谈ThreadLocal

1. ThreadLocal简介 ThreadLocal叫做线程变量,意思是ThreadLocal中填充的变量属于当前线程,该变量对其他线程而言是隔离的,也就是说该变量是当前线程独有的变量。ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。 ThreadLoal 变量,线程局部变量,同一个 ThreadLocal 所包含的对象,在不同的 Thread 中有不同的副本。这里有几点需要注意: 因为每个 Thread 内有自己的实例副本,且该副本只能由当前 Thr

大家好,我是千楼,全栈开发工程师,分享日常学习和工作,记录成长~~~ 5298

【2025最新版】ABAP 开发百科全书专栏文章目录(上)

本文汇总了一系列SAP ABAP技术文章,内容涵盖实用技巧合集、函数式编程实践(如Currying、reduce应用)、设计模式实现(如Visitor、Singleton)、动态代理与Mock技术、性能优化方案(如Lazy Loading)、日期处理与内存管理,以及ABAP与JavaScript的编程范式对比。还涉及CDS视图、Fiori字段追踪、单元测试优化等实战经验,深入剖析了ABAP底层机制(如Internal Session、Function Module实现原理),并提供了多种反模式改进方案。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 2484

结构力学仿真软件:STAAD.Pro:结构抗震设计与STAAD.Pro应用_2024-08-10_11-49-29.Tex

STAAD.Pro是一款广泛应用于结构工程领域的仿真软件,由Bentley Systems开发。它能够进行结构分析和设计,支持多种结构类型,包括桥梁、建筑物、塔架等。STAAD.Pro提供了强大的建模工具,用户可以轻松创建复杂的结构模型,并进行静态和动态分析。软件还支持多种载荷组合,包括地震载荷,以及提供详细的报告和图纸输出,便于工程师进行设计和审查。STAAD.Pro是一款广泛应用于结构工程设计的软件,其界面直观,功能强大,能够进行结构分析与设计。菜单栏。

977

图解 ThreadLocal

通过对 ThreadLocal 内存原理的深入分析,我们了解了它的工作机制以及可能存在的内存管理问题。合理使用 ThreadLocal,并注意内存泄漏的防范,可以让我们在多线程编程中更加得心应手。希望今天的分享能帮助你更好地理解和应用 ThreadLocal,在实际项目中发挥它的强大作用。如果你对 ThreadLocal 还有其他疑问,或者在多线程编程中遇到了其他问题,欢迎在留言区交流讨论。

未来的那个你 999

26. Fabric2.2 司法存证的智能合约分析

有很多同学反馈 Fabric 智能合约读起来比较费劲,对于新手不友好看不懂,这里选择一个司法存证的智能合约,阅读、分析智能合约基础框架与核心流程代码,培养大家智能合约编写的方法论。

菜鸟的博客 1340

并发编程-ThreadLocal

今天的文章很短,但是很经典,值得你仔细阅读每一个文字......... 正如我开篇所说,我们要整理一些java并发编程的学习文档,这一篇就是第七篇:ThreadLocal。主要聊聊ThreadLocal本质。希望对你有帮助。 ...

1894

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

图解,深入浅出带你理解ThreadLocal

ThreadLocal 是我们在学习java时必须优先掌握的内容,而且应用场景广泛。比如以前一些项目,会把前台传的一部分参数放入ThreadLocal,随线程流转;又或者我们经常使用的Spring框架的@Transactional注解,也用到了ThreadLocal。所以学习ThreadLocal,是一个必备,且越早学习越好的基础内容。

战斧的博客 6822

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

《 ThreadLocal 工作机制深度解析:高并发场景的利与弊》

ThreadLocal是高并发编程中的线程隔离神器,通过为每个线程维护独立变量副本实现无锁线程安全。其核心机制基于ThreadLocalMap的弱引用Entry结构,但存在内存泄漏风险(尤其是线程池场景),必须规范使用remove()清理。典型应用包括会话管理、链路追踪等上下文传递场景。对于线程池环境,推荐使用TransmittableThreadLocal实现跨线程值传递。最佳实践:1)始终在finally块清理ThreadLocal;2)避免存储大对象;3)线程池场景优先使用TTL方案。

qq_43414012的博客 1127

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

图解ThreadLocal核心原理

线程安全问题的本质:对共享资源进行访问 解决线程安全问题:加锁,互斥访问共享资源 多线程编程时,如果不操作共享变量,就没有线程安全问题了

javaThinker的专栏 615

图解ThreadLocal原理

在项目中不少地方会用到ThreadLocal对象,用来实现线程之间资源隔离。现在通过图的方式接解刨其原理。 public static void main(String[] arg) throws InterruptedException, IOException { final ThreadLocal t = new ThreadLocal(); Thread thread_1 = new Thread(new Runnable(){ @Overri

wo11201432的专栏 1030

ThreadLocal介绍和使用

ThreadLocal介绍和使用

chengbo_eva的博客 2033

ThreadLocal详解

get() 方法首先获取当前线程,然后尝试从当前线程的 ThreadLocalMap 中获取与当前 ThreadLocal 实例关联的值。如果找到了该值,则直接返回;否则调用 setInitialValue() 设置并返回初始值。getMap(Thread t) 方法返回当前线程的 ThreadLocalMap。> key) 方法通过计算哈希值获取与 key 关联的条目,如果没有找到,则调用 getEntryAfterMiss 继续查找。

落日的博客 2679

图解ThreadLocal

ThreadLocal ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序。   当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。   从线程的角度看,目标变量就象是线程的本地变量,这也

技海拾贝 1087

ThreadLocal 理解及面试

ThreadLocal的个人理解及面试问题附答案

am_Sun的博客 1757

图解ThreadLocal实现原理

图解ThreadLocal实现原理 ThreadLocal是java中用来为各个线程创建本地变量副本的类,它的实现比较特殊所以在面试等地方很容易被问到,这里做了一个简单的图帮助大家理解ThreadLocal类实现创建变量副本的原理。 大家可以很清楚的看到,其实本地变量是存储在每个Thread类中的threadLocals对象(ThreadLocalMap类)中的,这个类内部由一个Entry数组实...

qq_40247452的博客 438

【Java并发学习五】图解ThreadLocal

简单整理下ThreadLocal的原理,以及它需要注意的内存泄漏。 ThreadLocal原理 ThreadLocal不多介绍,可看作线程内的局部变量(这个比喻很贴切)。我们平时声明的局部变量的范围一般是方法内的,而ThreadLocal变量的范围是整个线程。 我们先来看一段代码demo: public class Test { //可看作线程内声明的局部变量 st...

大树的学习之路 1664
上一篇: 想用K8s,还得先会Docker吗?其实完全没必要
下一篇: 一文搞定 Spring Security 异常处理机制!
Java技术那些事儿
博客等级 码龄5年 2306粉丝 2584原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值