ThreadLocal原理以及其安全问题

2023-10-26

ThreadLocal 是一个线程内共享数据的类,其原理是在线程有一个 ThreadLocalMap,key是ThreadLocal对象,value是自定义的数据,所以在同一个线程中,用同一个threadlocal去get数据,能取到同样的数据。实现线程内数据共享。

ThreadLocalMap

在这里插入图片描述
说白了 ThreadLocalMap 就是有一个 Entry 的数组, Entry就是一个有着两个成员变量的类。一个变量是 value , 另一个成员变量 在继承的 WeakReference 里面,是 referent当GC的时候这个成员变量就会被释放
在这里插入图片描述
threadLocal 用法很简单,就是set 和get不做过多赘述。我们来看看为什么ThreadLocalMap的key要做成 WeakReference .
我们先来看如下的引用关系:

在这里插入图片描述
如果entry的那个弱引用改成强引用的话,那么在很多情况下, 线程的生命周期和程序是相同的,那么就算用户 threadLocal = null; 想要释放threadLocal的内存地址,也没用。造成内存泄漏。所以设计成弱引用的时候,当用户想要释放threadLocal 资源的时候(虽然很少) threadLocal = null; 线程的弱引用也会在下次GC的时候回收。
那么问题来了,为什么value不也设计成弱引用呢?
因为最根本的原因是因为 key 和 value 的生命周期是不一样的。 key 和 value是两个代码创建出来的,他们并不能保证一起消失,所以当 value如果设计成弱引用的时候,可能value指向消失了,但是key的强引用还存在,那么就可能出现key存在但是get不到东西的情况。

内存泄漏问题

上面说了,为了保证key一定能get到value的情况。在线程中强引用了value,那么这个value的生命周期就和该线程相同了。造成了内存泄漏。 就算在ThreadLocalMap里面的添加方法的时候会去删除key为空的value
条件是

  1. hash冲突会判空删除
  2. 插入的下标往后遍历查找为空的数据删除
        private void set(ThreadLocal<?> key, Object value) {
            Entry[] tab = table;
            int len = tab.length;
            int i = key.threadLocalHashCode & (len-1);
            for (Entry e = tab[i];
                 e != null;
                 e = tab[i = nextIndex(i, len)]) {
                ThreadLocal<?> k = e.get();

                if (k == key) {
                    e.value = value;
                    return;
                }
               
                if (k == null) {
                # 在hash冲突的时候, 如果上一个key为空,就把value给删了
                    replaceStaleEntry(key, value, i);
                    return;
                }
            }
            tab[i] = new Entry(key, value);
            int sz = ++size;
            # 插入当前的地址往后遍历一波,查看有没有value为空的数据
            if (!cleanSomeSlots(i, sz) && sz >= threshold)
                rehash();
        }

即使是有这样的判断,如果key在数据之前,并且没有hash碰撞,那么value也永远都删除不掉。
所以在用完value之后一定要主动调用remove让线程删除引用, remove方法最终调用如下
在这里插入图片描述

数据错误问题

有的人可能觉得,自己的threadLocal是静态变量,生命周期本来就跟项目相同,并且一个项目中线程几十个存放的也都是一些用户数据,没有太多的泄漏。那么ThreadLocal就还会因此引发第二个问题,数据错误。
现在项目中大部分都采用线程池技术,Tomcat,Apache 等等。
如果在这一次请求中存入了用户的数据没有释放,在其他用户访问的时候可能复用了当前线程,然后取出来的还是上一个用户的数据

ThreadLocal 线程共享

Thread 类里面还有一个成员变量 inheritableThreadLocals 可以用来做父子线程的数据共享,原理很简单,就是在创建线程的时候判断父线程的这个变量有没有值,如果有值,则也拷贝一份到自身。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ThreadLocal原理以及其安全问题 的相关文章

  • 如果我在 XML 布局中声明一个片段,如何将它传递为 Bundle?

    我有一个活动已替换为片段 该活动采用了一个 Intent 其中包含一些有关该活动应该显示哪些数据的额外信息 现在 我的 Activity 只是执行相同工作的 Fragment 的包装器 如果我使用标记在 XML 中声明该片段 如何将该捆绑包
  • 从 java servlet 运行长进程的最佳方法是什么?

    我想问从 java servlet 运行长进程的最佳方法是什么 我有一个网络应用程序 当客户端发出请求时 它会运行一个 servlet 该 servlet 应该从请求中获取一些参数 然后运行一个进程 这个过程可能需要很长时间 所以我需要单独
  • Maven:在项目之间共享源

    我有两个项目 它们是一个共同父项目的子项目 还有一个生成器项目和生成器对应的maven插件项目 此外 两个子项目都使用相同的输入文件 该文件用于代码生成 parent pom child1 jar src main generator in
  • 如何设置评分栏的星星颜色?

    如何设置评分栏的星星颜色 我想要黄色星星 最简单的方法 android progressTint color color 光滑有光泽
  • Glide:如何使用 Glide v4 调整 gif 大小并将其另存为文件?

    我想调整 gif 文件的大小并保存它 我尝试使用一些建议的方法 但这些方法给出了错误 后来我知道有些方法在 Glide 中已被弃用v4 byte bytes Glide with context asGif load url toBytes
  • 如何在angularjs中读取pdf流

    I got the following PDF stream from a server 如何在 AngularJS 中读取这个流 我尝试使用以下代码在新窗口中将其作为 PDF 文件打开 success function data wind
  • Java程序在没有定义main方法的情况下如何运行?

    我正在浏览一些 Java 源代码并注意到main方法未定义 Java如何编译源码却无从下手 The main方法仅在 Java 虚拟机执行代码时使用 没有 a 则无法执行代码main方法 但仍然可以编译 编译代码时 通常在命令行上指定一组文
  • emacs 的最佳 java 工具 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 更改单击后退按钮上的 BottomNavigationView 图标

    在我的布局的底部有一个底部导航视图与三个片段 如果我单击后退按钮 片段将切换 但底部图标不会切换 我该如何修复它 addToBackStack 有效 也许您有一些关于美化代码的建议 在活动或片段中添加片段标签是一个好的做法吗 public
  • 无法在IntelliJ IDEA中编译和运行java代码

    使用 IntelliJ IDEA 版本 12 1 6 我想运行 Horstmann Core Java 书中的示例 public class Welcome public static void main String args Strin
  • Swing 是否支持 Windows 7 风格的文件选择器?

    我刚刚添加了一个标准 打开文件 与我正在编写的一个小型桌面应用程序的对话 基于JFileChooserSwing 教程的入口 http download oracle com javase tutorial uiswing componen
  • 从壁纸中获取颜色? - 安卓

    如何找到当前壁纸的 平均 颜色并将该颜色设置为我的小部件上的布局 我正在尝试做的一个例子 这是 AccuWeather 上的设置 您可以使用WallpaperManager getWallpaperColors https develope
  • 在 JSON 转换为 CSV 期间保持 JSON 键的顺序

    我正在使用此处提供的 JSON 库http www json org java index html http www json org java index html为了将 json 字符串转换为 CSV 但我遇到的问题是 转换后键的顺序
  • 如何设置 Eclipse 以停止发生异常的线路?

    如何设置 Eclipse 在发生异常时停止 我有一个 Eclipse 断点设置来在异常时中断 在下面的代码示例中 我遇到的问题是 Eclipse 尝试打开 Integer 源代码 有没有办法让调试器在我的代码示例中显示的位置中断 如果我向下
  • 带有 Spock Stub 的泛型

    我无法为泛型类编译 Spock 存根 构造函数的签名如下 SomeClass SerSup
  • Java TreeMap时间复杂度-lowerKey

    时间复杂度是多少lowerKey Java实现中的操作TreeMap 我认为它是 log n 但我在文档中找不到它 更基本操作的复杂性已有详细记录 此实现提供了有保证的 log n 时间成本 containsKey 获取 放置和删除操作 顺
  • 如果表不存在,如何使用 Derby Db 创建表

    我是新来的apache derby我似乎无法工作 CREATE TABLE IF NOT EXISTS table1 可以实现MySql等等我得到了 Syntax error Encountered NOT at line 1 column
  • GAE、JPA、XG 事务、实体组过多异常

    我知道 GAE 上的 XG 交易有 5 个实体组的限制 但我认为我在一项交易中仅使用 3 个组 商品 类别 商品类别 但仍然遇到此异常 引起原因 java lang IllegalArgumentException 在单个事务中对太多实体组
  • 编写代码以:启动 R 会话、运行 R 脚本、终止会话、重复

    我正在寻找一种简单的 设置后就忘记它 的方式 无论是作为终端中的单个参数字符串还是简单的 Java 程序 来自动执行以下操作 1 启动R会话 2 告诉 R 源 R 文件包含冗长的并行模拟代码 3 完成后终止R会话 4 开始一个新的R会话 5
  • OutputStream 到 DB2 数据库表的 BLOB 列

    在 DB2 数据库中 我有下表 CREATE TABLE MyTestTable MYPATH VARCHAR 512 NOT NULL MYDATA BLOB CONSTRAINT MYTESTTABLE PK PRIMARY KEY M

随机推荐

  • App逆向案例 X嘟牛 - Frida监听 & WT-JS工具还原(一)

    App逆向案例 X嘟牛 Frida监听 WT JS工具还原 一 提示 文章仅供参考 禁止用于非法途径 文章目录 App逆向案例 X嘟牛 Frida监听 WT JS工具还原 一 前言 一 资源推荐 二 App抓包分析 三 反编译逆向分析 四
  • 2023华为产品测评官-开发者之声

    2023华为产品测评官 开发者之声 活动激发了众多开发者和技术爱好者的热情 他们纷纷递交了精心编写的产品测评报告 活动社群充满活力 参与者们热衷于交流讨论 互相帮助解决问题 一起探索云技术的无限可能 在此次活动中 华为云CodeArts获得
  • 守护线程

    守护线程是一类比较特殊的线程 一般用于处理后台的工作 比如JDK的垃圾回收线程 守护线程具备自动结束生命周期的特点 非守护线程不具备这样的特点 首先明确一个问题 JVM什么情况下会退出 The java virtual machine ex
  • 关于H.248的树图规则

    一 H248数图 数图可以是一个字符串 我们不妨称之为数图字符串 它遵循了Unix系统命令中的规则表达式的语法规定 也可以是许多数图字符串的并集 之间用 分隔 我们不妨称之为数图字符串列表 以下是一个数图的例子 2 8 xxxxxxx 13
  • RabbitMQ 与 Kafka 对比

    作为一个有丰富经验的微服务系统架构师 经常有人问我 应该选择RabbitMQ还是Kafka 基于某些原因 许多开发者会把这两种技术当做等价的来看待 的确 在一些案例场景下选择RabbitMQ还是Kafka没什么差别 但是这两种技术在底层实现
  • 【jackson】自定义字段注解完成序列化逻辑

    目录 背景 本文开发环境介绍 新建一个注解 新建一个JavaBean 新建一个JsonSerializer 新建一个AnnotationIntrospector 单元测试 总结 背景 Spring默认的JSON序列化工具使用的是jackso
  • 基于CNN-LSTM数据分类:Matlab实现

    基于CNN LSTM数据分类 Matlab实现 在当今的信息时代 数据处理和分类已经成为了不可或缺的技能和工具 其中卷积神经网络 Convolutional Neural Network CNN 和长短时记忆网络 Long Short Te
  • 多少存款才是裸辞的最好姿态?

    朋友小惠上个月裸辞了 前几天见她还意气风发 没想到昨晚就和我说 焦虑来得远比想象中快 她的计划是三个月内找到满意的新工作 满打满算攒了三个月的生活费才踏出裸辞这一步 结果面试了几个公司后 对于能否在三个月内找到满意工作感到极度地焦虑 小惠认
  • [SWPUCTF 2021 新生赛]finalrce

  • tplink 703n lede -17.01 编译过程

    tplink 703n lede 17 01 编译过程 tplink 703n lede 17 01 编译过程 tplink 703n 支持USB扩展 利用其功能可实现挂载硬盘 打印机共享等 网上虽然有些现成的固件 但基于openwrt 1
  • shiro(java安全框架)

    以下都是综合之前的人加上自己的一些小总结 Apache Shiro是一个强大且易用的Java安全框架 执行身份验证 授权 密码学和会话管理 使用Shiro的易于理解的API 您可以快速 轻松地获得任何应用程序 从最小的移动应用程序到最大的网
  • SQL - MySQL回表

    一 回表概念 现象 回表 顾名思义就是回到表中 也就是先通过普通索引 我们自己建的索引不管是单列索引还是联合索引 都称为普通索引 扫描出数据所在的行 再通过行主键ID 取出索引中未包含的数据 所以回表的产生也是需要一定条件的 如果一次索引查
  • 怎么用计算机算ess tss,"ESS、RSS、TSS"分别表示什么?

    回归平方和 ESS 残差平方和 RSS 总体平方和 TSS 1 回归平方和 是反映自变量与因变量之间的相关程度的偏差平方和 用回归方程或回归线来描述变量之间的统计关系时 实验值yi与按回归线预测的值Yi并不一定完全一致 2 残差平方和是在线
  • 通过Android Studio 将yolov5部署到手机端(2023新手最新适用版)

    通过Android Studio 将yolov5部署到手机端 2023新手最新适用版 java17安装 下载java17 Java Downloads Oracle 配置环境变量 这个是我安装后的路径 将这个路径复制 设置环境变量 在系统变
  • Qt技巧:QProcess与外部程序的调用

    项目做到一定阶段 常常须要在原来的project上调用外部程序 Qt为此提供了QProcess类 QProcess可用于完毕启动外部程序 并与之交互通信 一 启动外部程序的两种方式 1 一体式 void QProcess start con
  • NFS服务安装配置(centos7 nfs-utils示例)

    测试机器 nps server 10 166 205 104 nfs client 10 166 205 101 server端 安装nfs utils和rpcbind sudo yum install nfs utils rpcbind
  • np.random里让你迷糊的随机数函数到底咋区分(结合tensorflow)

    小测 numpy以下哪个函数不能产生正态分布的随机数 A standard normal B randn C random D normal 从 0 1 范围的标准分布中产生1个随机数 以下哪个numpy函数是错误的 A rand B ra
  • Sort 【HDU - 5884】【哈夫曼树】

    题目链接 一开始看到题的时候 竟然读成了是按照升序排序的一串数 害得我WA了两发 还以为是补0补错了 研究了一会补0发现好像没有多大问题 然后就继续了 直到再看了遍题 发现好像是没有给你拍好序的 然后AC 这道题其实哈夫曼树不难 就是补0思
  • 【信创】麒麟操作系统配置在线源及手动查找所需软件包

    获取操作系统信息 命令 nkvers 关注倒数第2行 示例中大版本 V10 小版本 SP2 CPU架构 aarch64 root localhost nkvers Kylin Linux Version Release Kylin Linu
  • ThreadLocal原理以及其安全问题

    ThreadLocal 是一个线程内共享数据的类 其原理是在线程有一个 ThreadLocalMap key是ThreadLocal对象 value是自定义的数据 所以在同一个线程中 用同一个threadlocal去get数据 能取到同样的