【Java】ThreadLocal原理

news2024/10/2 3:24:04

​ ThreadLocal

ThreadLocal意为线程本地变量,用于解决多线程并发时访问共享变量的问题。
在这里插入图片描述
每个线程都会有属于自己的本地内存,在堆(也就是上图的主内存)中的变量在被线程使用的时候会被复制一个副本线程的本地内存中,当线程修改了共享变量之后就会通过JMM管理控制写会到主内存中。

ThreadLoal 变量,线程局部变量,同一个 ThreadLocal 所包含的对象,在不同的 Thread 中有不同的副本。这里有几点需要注意:

  • 因为每个 Thread 内有自己的实例副本,且该副本只能由当前 Thread 使用。这是也是 ThreadLocal 命名的由来。
  • 既然每个 Thread 有自己的实例副本,且其它 Thread 不可访问,那就不存在多线程间共享的问题。

​ 很明显,在多线程的场景下,当有多个线程对共享变量进行修改的时候,就会出现线程安全问题,即数据不一致问题。常用的解决方法是对访问共享变量的代码加锁(synchronized或者Lock)。但是这种方式对性能的耗费比较大。在JDK1.2中引入了ThreadLocal类,来修饰共享变量,使每个线程都单独拥有一份共享变量,这样就可以做到线程之间对于共享变量的隔离问题。

当然锁和ThreadLocal使用场景还是有区别的,具体区别如下

synchronized(锁)ThreadLocal
原理同步机制采用了时间换空间的方式,只提供一份变量,让不同线程排队访问(临界区排队)采用空间换时间的方式,为每一个线程都提供一份变量的副本,从而实现同时访问而互不相干扰
侧重点多个线程之间访问资源的同步多线程中让每个线程之间的数据相互隔离

二、原理

每个Thread对象都有一个ThreadLocalMap,当创建一个ThreadLocal的时候,就会将该ThreadLocal对象添加到该Map中,其中键就是ThreadLocal,值可以是任意类型。

前面我们的理解是所有的常量值或者是引用类型的引用都是保存在ThreadLocal实例中的,但实际上不是的,这种说法只是让我们更好的理解ThreadLocal变量这个概念。

ThreadLocal存入一个值,实际上是向当前线程对象中的ThreadLocalMap存入值,ThreadLocalMap我们可以简单的理解成一个Map,而向这个Map存值的key就是ThreadLocal实例本身。

Key的弱引用问题

为什么要用弱引用,官方是这样回答的

To help deal with very large and long-lived usages, the hash table entries use WeakReferences for keys.
为了处理非常大和生命周期非常长的线程,哈希表使用弱引用作为key。

生命周期长的线程可以理解为:线程池的核心线程

ThreadLocal在没有外部对象强引用时如Thread,发生GC时弱引用Key会被回收,而Value是强引用不会回收,如果创建ThreadLocal的线程一直持续运行如线程池中的线程,那么这个Entry对象中的value就有可能一直得不到回收,发生内存泄露。

  • key 使用强引用: 引用的ThreadLocal的对象被回收了,但是ThreadLocalMap还持有ThreadLocal的强引用,如果没有手动删除,ThreadLocal不会被回收,导致Entry内存泄漏。
  • key 使用弱引用: 引用的ThreadLocal的对象被回收了,由于ThreadLocalMap持有ThreadLocal的弱引用,即使没有手动删除,ThreadLocal也会被回收。value在下一次ThreadLocalMap调用setgetremove的时候会被清除。

Java8中已经做了一些优化如,在ThreadLocalget()set()remove()方法调用的时候会清除掉线程ThreadLocalMap中所有EntryKeynullValue,并将整个Entry设置为null,利于下次内存回收。

三、方法

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/369982.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【H5 | CSS | JS】如何实现网页打字机效果?快收下这份超详细指南(附源码)

💂作者简介: THUNDER王,一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学会计学专业大二本科在读,同时任汉硕云(广东)科技有限公司ABAP开发顾问。在学习工作中,我通常使用偏后…

在C#中初测OpencvSharp4

一、配置OpenCV 首先,我们新建一个工程,然后就是给这个工程配置OpenCV了,最简单的方法还是Nuget,来我们右键一个Nuget: 打开Nuget后,你可以直接输入OpenCVSharp4来查找,当然,如果你…

公司新来的00后真是卷王,工作没两年,跳槽到我们公司起薪20K都快接近我了

都说00后躺平了,但是有一说一,该卷的还是卷。这不,前段时间我们公司来了个00后,工作都没两年,跳槽到我们公司起薪18K,都快接近我了。后来才知道人家是个卷王,从早干到晚就差搬张床到工位睡觉了。…

罗永浩进场之后,苹果入局之前:XR又寒冬了吗?

科技圈的悲欢并不相通。ChatGPT狂飙之际,XR领域正在迎来至暗时刻。岁末年初,就在罗永浩重返高科技创业,计划进军XR(扩展现实)类领域的时间段前后,接连出现了押注元宇宙的Meta裁员,Meta旗下VR工作室Ready At…

【华为OD机试模拟题】用 C++ 实现 - 快递业务站(2023.Q1)

最近更新的博客 华为OD机试 - 入栈出栈(C++) | 附带编码思路 【2023】 华为OD机试 - 箱子之形摆放(C++) | 附带编码思路 【2023】 华为OD机试 - 简易内存池 2(C++) | 附带编码思路 【2023】 华为OD机试 - 第 N 个排列(C++) | 附带编码思路 【2023】 华为OD机试 - 考古…

【华为OD机试模拟题】用 C++ 实现 - 流水线(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 分积木(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 吃火锅(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - RSA 加密算法(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 构成的正方形数量(2023.Q1) 【华为OD机试模拟…

数据库|(六)连接查询

(六)连接查询1. 笛卡尔乘积2. 连接查询分类2.1 按年代分2.2 按功能分3. 等值连接(sql 92标准)3.1 特点3.2 一般使用3.3 为表取别名3.4 两表顺序可以调换3.5 可以加筛选3.6 可以加分组3.7 可以加排序3.8 可以实现三表连接4. 非等值连接(sql 92标准)5. sql…

【深度学习】GPT系列模型:语言理解能力的革新

GPT-1🏡 自然语言理解包括一系列不同的任务,例如文本蕴涵、问答、语义相似度评估和文档分类。尽管大量的未标记文本语料库很充足,但用于学习这些特定任务的标记数据却很稀缺,使得判别式训练模型难以达到良好的表现。我们证明&…

Spring(入门)

1. 什么是spring,它能够做什么?2. 什么是控制反转(或依赖注入)3. AOP的关键概念4. 示例 4.1 创建工程4.2 pom文件4.3 spring配置文件4.4 示例代码 4.4.1 示例14.4.2 示例2 (abstract,parent示例)4.4.3 使用有参数构造方法创建jav…

【华为OD机试模拟题】用 C++ 实现 - 找数字(2023.Q1)

最近更新的博客 华为OD机试 - 入栈出栈(C++) | 附带编码思路 【2023】 华为OD机试 - 箱子之形摆放(C++) | 附带编码思路 【2023】 华为OD机试 - 简易内存池 2(C++) | 附带编码思路 【2023】 华为OD机试 - 第 N 个排列(C++) | 附带编码思路 【2023】 华为OD机试 - 考古…

显示器管理工具:BetterDisplay Pro Mac

BetterDisplay Pro Mac 是一个非常棒的工具!它可以让您将显示器转换为完全可缩放的屏幕,允许亮度控制,提供 XDR/HDR 升级(在兼容显示器上超过 100% 的额外亮度),完全调光为黑色,帮助您为 Mac 创…

PRML笔记3-绪论中最小化错误分类率的理解

这个小节的内容很少,因为自己数学水平实在太差,所以理解不到之处还请批评指正。 在分类任务中我们希望尽可能减少错误的分类,例如我们有一些病人的临床数据,希望通过这些临床数据对患者的诊断提供帮助,比如根据临床数据…

gazebo仿真环境中添加robotiq 2f 140的gripper_controller控制器

gazebo仿真环境中添加robotiq 2f 140的gripper_controller控制器 搭建环境: ubuntu: 20.04 ros: Nonetic sensor: robotiq_ft300 gripper: robotiq_2f_140_gripper UR: UR3 reasense: D435i 通过下面几篇博客配置好了ur3、力传感器、robotiq夹爪、rea…

vuejs文件传参方式

vue2版本 vscode 大致总结一下几种情况: 1.父传子,父组件利用props向子组件传递数据 1.在父组件的子组件标签上绑定一个属性,挂载要传输的变量 2.在子组件中通过props来接受数据,props可以是数组也可以是对象,接受的数…

RayVentory updated

RayVentory updated RayVentory Aspera连接器12.5.0.11850[更新1] 增加了对Docker容器的支持。 已将Xen虚拟机的设备类型更改为“Virtual_Machine”。 RayVentory扫描引擎12.5.3579.69[更新1] 添加了法语UI翻译预览。 RayVentory提供了硬件和软件的全面清单,并提供了…

mars3d获取视窗的范围

期望效果 :1.我现在想获取到当前视窗的地图范围,请问有什么⽅法可以拿到吗 2.⽐如当前视窗地图范围的边界点,每个边界点的经纬度 回复:1.mars3d的API⽂档中有相关的⽅法 2.具体使⽤可以参考⽂档地址:http://mars3d.cn/api/Map.htm…

长期跑步需要买个运动耳机吗、最好用的5款跑步耳机推荐

告别了寒冬,迎来了暖春。我的健身计划也开始提上了日程。最开始跑步还有点新鲜感,但是时间一久,自己在公园跑步那种枯燥感就会袭来,一个坚持跑步一年多的朋友告诉我,可以试一下跑步时听听音乐,既能锻炼身体…

JVM虚拟机栈

1、概述Java虚拟机栈(Java Virtual Machine Stack),早期也叫Java栈。每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧(Stack Frame),对应着一次次的Java方法调用,是线…

Codeforces Round #850 (Div. 2, based on VK Cup 2022 - Final Round)(A~E)

t宝酱紫喜欢出这种分类讨论的题&#xff1f;&#xff01;A1. Non-alternating Deck (easy version)给出n张牌&#xff0c;按照题目给的顺序分给两人&#xff0c;问最后两人手中各有几张牌。思路&#xff1a;模拟。AC Code&#xff1a;#include <bits/stdc.h>typedef long…

SpringBoot+Vue前后端分离管理系统03:后端

后端项目初始化 1、创建一个springboot 2.7.8项目 2、导入依赖 <!-- web --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- mysql -->…