ThreadLocal “你”真的了解吗?

news2024/11/25 19:17:47

今天想梳理一个常见的面试题。在开始之前,让我们一起来回顾一下昨天的那篇文章——《Spring 事务原理总结七》。这篇文章比较啰嗦,层次也不太清晰,所以以后有机会我一定要重新整理一番。这篇文章主要想表达这样一个观点:Spring的嵌套事务是通过ThreadLocal实现的。当一个请求从浏览器发送到后台以后,后台会启动一个线程去处理这个请求,在处理的过程中如果用到了一个需要事务的方法A,而A又调用了另一个需要事务的方法B,那么这时就发生了事务嵌套(同时还涉及到了事务传播行为,即事务A与事务B之间的相互关系)。为了解决事务嵌套的问题,Spring又定义了一个记录与事务相关的信息的类TransactionInfo。这样A就有了一个对应的TransactionInfo对象,B也有了一个对应的TransactionInfo对象。而A调用了B,所以A和B对应的TransactionInfo对象之间就有了关联关系。在TransactionInfo类中有一个oldTransactionInfo属性,这个记录的就是老的事务对象。看过前面系列文章又好好思考过的童鞋可能已经明白了,在A中通过代理调用B的时候,此时两个事务位于同一线程中,接着将A对应的TransactionInfo对象赋值给B对应的TransactionInfo对象的oldTransactionInfo属性,然后将B对应的TransactionInfo对象绑定到ThreadLocal,接着待B执行完后,将当前线程绑定的TransactionInfo还原为A对应的TransactionInfo,此时就完成了嵌套事务之间信息传递。具体参见下面这幅图:

 上面这幅图并不完美,但将前面一段的描述图形化,这应该会好理解一点吧!在这段回顾中,我们不断提到ThreadLocal,那它究竟是干什么的?原理又是什么呢?想必大家也都听说过,ThreadLocal存在内存泄漏的风险,这又是咋回事呢?

概述

ThreadLocal,即线程本地变量,是Java中用于提供线程局部存储的类,位于java.lang包下它的核心原理在于为每个使用ThreadLocal的线程创建一个独立的副本,使得每个线程在访问ThreadLocal时获取到的是自己线程内的私有数据,而不是共享同一份数据,从而避免了多线程间的同步问题。其工作机制是这样的:

  • 内部存储结构:ThreadLocal内部维护了一个Map数据结构,其键是当前的线程对象(ThreadLocal.ThreadLocalMap),值是我们想要隔离存储的对象实例这意味着每个线程都有一个独立的ThreadLocalMap来保存自己的ThreadLocal副本
  • 存取操作:
  1. set(T value)方法允许我们设置线程局部变量的值。它会将给定的值与当前执行线程关联起来,在该线程的ThreadLocalMap中存储
  2. get()方法则返回当前线程所对应的ThreadLocal变量的副本值。如果该线程尚未初始化,则可能返回默认值或抛出异常
  3. remove():移除线程本地变量。注意在线程池的线程复用场景中在线程执行完毕时一定要调用remove,避免在线程被重新放入线程池中时被本地变量的旧状态仍然被保存。
  • 线程生命周期管理:当线程结束生命周期后,其内部的ThreadLocalMap应该被清理以释放资源然而,如果线程不再使用某个ThreadLocal但未手动删除引用,可能会导致内存泄漏,因为ThreadLocalMap中的Entry不会自动移除
  • 弱引用与内存泄漏:在内部实现上,ThreadLocalMap的条目是通过弱引用(WeakReference)指向ThreadLocal实例的,这意味着只有当没有强引用指向ThreadLocal实例时,这些条目才能被垃圾回收器回收。但如果仅ThreadLocalMap中的条目持有目标对象的唯一引用,即使线程已经完成任务,由于弱引用的存在,目标对象也不会立即被回收,这可能导致无用对象占据内存空间,直到下次JVM进行垃圾回收周期时才可能清除。
  • 使用场景:ThreadLocal常用于需要在线程间隔离状态信息的情况,例如数据库连接、事务上下文、用户身份信息等,尤其是在处理每个线程都需要独立的实例且不希望影响其他线程的情况下。

总的来说,ThreadLocal通过为每个线程维护一份独立的数据副本,巧妙地实现了多线程环境下的数据隔离和安全性,并简化了代码的编写,减少了同步块或锁的使用。但它也要求开发者关注并正确管理其生命周期,以免引发内存泄露问题。

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

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

相关文章

对于软件测试的理解

前言 “尽早的介入测试,遇到问题的解决成本就越低” 随着软件测试技术的发展,测试工作由原来单一的寻找缺陷逐渐发展成为预防缺陷,探索测试,破坏程序的过程,测试活动贯穿于整个软件生命周期中,故称为全程…

【SpringBoot】项目启动增加自定义Banner

SpringBoot项目启动增加自定义Banner 前言 最近有个老哥推荐我给博客启动的时候加上自定义Banner,开始我还不太明白他说的是那部分,后面给我发了这样一个,瞬间就懂了~ // _ooOoo_ …

Python(九十三)函数的参数总结

❤️ 专栏简介:本专栏记录了我个人从零开始学习Python编程的过程。在这个专栏中,我将分享我在学习Python的过程中的学习笔记、学习路线以及各个知识点。 ☀️ 专栏适用人群 :本专栏适用于希望学习Python编程的初学者和有一定编程基础的人。无…

不要0!我们需要1!

解法一&#xff1a; 十进制转二进制同时数1的个数 #include<iostream> #define endl \n using namespace std; void solve(int x) {int cnt 0;while (x) {if (x % 2 1) cnt;x / 2;}cout << cnt << endl; } int main() {int n;cin >> n;solve(n);re…

2024-2-19 LC200. 岛屿数量

其实还是用并查集将 独立的岛屿视为独立的子集。 count其实是集合的个数&#xff0c;同一个块岛屿被压缩成了一个集合&#xff0c;而每个表示海洋的格子依然被看作独立的集合&#xff0c;在所有的格子都走完一遍后&#xff0c;count 被压缩的岛屿 所有表示海洋的独立格子的数…

2024.2.19

使用fread和fwrite完成两个文件的拷贝 #include<stdio.h> #include<stdlib.h> #include<string.h> int main(int argc, const char *argv[]) {FILE *fpNULL;if((fpfopen("./tset.txt","w"))NULL){perror("open error");retur…

免费白嫖一个互联网创业者交流论坛,真香!

先说最重要的 当前小报童39.9&#xff0c;2.23之后会涨价到99.9 现在扫码购买&#xff0c;然后凭借截图找我全款报销&#xff0c;全款报销&#xff01; 扫码报销&#xff0c;备注“烽狂创客” 下面来看下这个专栏的内容 专栏作者是谁 挽歌&#xff0c;20岁&#xff0c;985大…

1. 处理日期和时间的 chrono 库

1. 处理日期和时间的 chrono 库 C11 中提供了日期和时间相关的库 chrono&#xff0c;通过 chrono 库可以很方便地处理日期和时间&#xff0c;为程序的开发提供了便利。chrono 库主要包含三种类型的类&#xff1a;时间间隔duration、时钟clocks、时间点time point。 1.1 基本常…

[计算机网络]---Https协议

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、https协…

课上题目代码

dijkstra和spfa区别 &#xff1a; dikstra是基于贪心的思想&#xff0c;每次选择最近的点去更新其它点&#xff0c;过后就不再访问。而在spfa算法中&#xff0c;只要有某个点的距离被更新了&#xff0c;就把它加到队列中&#xff0c;去更新其它点&#xff0c;所有每个点有被重…

Java中的线程(创建多线程的三种方法)

Java中的线程——创建 创建多线程方式一&#xff1a;继承Thread类方式二&#xff1a;实现Runnable接口方式三&#xff1a;实现Callable接口 线程的常用API 创建多线程 方式一&#xff1a;继承Thread类 定义一个子类MyThread继承线程类java.lang.Thread&#xff0c;重写run方法…

vue3+ts项目搭建

⛰️个人主页: 蒾酒 &#x1f525;系列专栏&#xff1a;《vue3实战》 &#x1f30a;山高路远&#xff0c;行路漫漫&#xff0c;终有归途。 目录 前置条件 基础工程模板搭建 测试环境变量是否配置成功 初始化vue项目 安装常用依赖 基础项目目录介绍 前置条件 请确…

自动化测试框架搭建全过程

前段时间写了一系列自动化测试相关的文章&#xff0c;当然更多的是方法和解决问题的思路角度去阐述我的一些观点。这篇文章来聊聊新手如何从零到一落地实践接口自动化测试。 为什么要做接口测试 测试理念的演变 早些时候&#xff0c;软件研发交付流程大多遵循V型或W型的瀑布…

9、内网安全-横向移动Exchange服务有账户CVE漏洞无账户口令爆破

用途&#xff1a;个人学习笔记&#xff0c;有所借鉴&#xff0c;欢迎指正&#xff01; 背景&#xff1a; 在内网环境的主机中&#xff0c;大部分部署有Exchange邮件服务&#xff0c;对于Exchange服务的漏洞也是频出&#xff0c;在这种情况下&#xff0c;如果拿到内网中一台主机…

2024 年 2 月 TIOBE 指数:最流行的 10 种编程语言

Go 进入了 TIOBE 指数的前 10 名&#xff0c;这是谷歌编程语言有史以来的最高位置。 在 2024 年 2 月的 TIOBE 软件最受欢迎的编程语言列表中&#xff0c;Python、C 和 C 保持了它们的领先地位&#xff08;图 A&#xff09;。TIOBE 的专有积分系统考虑了根据多种大型搜索引擎&…

office的excel中使用,告诉我详细的解决方案,如何变成转化为金额格式

在Office的Excel中&#xff0c;如果你想将名为"MEREFIELD"的公式结果转换为金额格式&#xff0c;你可以遵循以下详细步骤来实现&#xff1a; 书写MEREFIELD公式&#xff1a; 首先&#xff0c;在Excel中输入或确认你的MEREFIELD公式。例如&#xff0c;假设这个公式是用…

剑指offer刷题笔记-链表

少年何妨梦摘星 敢挽桑弓射玉衡 解决与链表相关的问题总是有大量的指针操作&#xff0c;而指针操作的代码总是容易出错的。很多面试官喜欢出与链表相关的问题&#xff0c;就是想通过指针操作来考察应聘者的编码功底。 题目链接来自于 AcWing 、Leetcode&#xff08;LCR&#xf…

微信美容预约小程序开发实战教程,快速掌握开发技巧

如果你想开发一个美容美发小程序&#xff0c;以下是一个搭建指南&#xff0c;供你参考。 1. 使用第三方制作平台 首先&#xff0c;你需要使用一个第三方制作平台&#xff0c;如乔拓云网。在该平台上&#xff0c;你需要注册并登录&#xff0c;然后点击【轻应用小程序】进入设计…

自动化测试框架搭建

思想&#xff1a; 1、基本目录的搭建 report:静态输出目录(报告或者日志) data&#xff1a;静态输入目录(可以存放Excel数据&#xff0c;被读取的一些数据) utils:实用方法层(这里存放的是项目的公共方法&#xff0c;一般拿到别…

2024年2月12日-2月18日周报

文章目录 1. 本周计划2. 完成情况2.1 论文摘要2.2 数据集2.3 基准测试 3. 总结及收获4. 下周计划 1. 本周计划 阅读论文《 E F W I E^{FWI} EFWI: Multiparameter Benchmark Datasets for Elastic Full Waveform Inversion of Geophysical Properties》 了解一种新型的数据集&…