对ThreadLocal实现原理的一点思考
前言
在《透彻理解Spring事务设计思想之手写实现》中,已经向大家揭示了Spring就是利用ThreadLocal来实现一个线程中的Connection是同一个,从而保证了事务。本篇博客将带大家来深入分析ThreadLocal的实现原理。
ThreadLocal是什么、有什么、能做什么?
ThreadLocal提供一个线程(Thread)局部变量,访问到某个变量的每一个线程都拥有自己的局部变量。说白了,ThreadLocal就是想在多线程环境下去保证成员变量的安全。
ThreadLocal提供的方法
对于ThreadLocal而言,常用的方法,就是get/set/initialValue方法。
我们先来看一个例子
运行结果
很显然,在这里,并没有通过ThreadLocal达到线程隔离的机制,可是ThreadLocal不是保证线程安全的么?这是什么鬼?
虽然,ThreadLocal让访问某个变量的线程都拥有自己的局部变量,但是如果这个局部变量都指向同一个对象呢?这个时候ThreadLocal就失效了。仔细观察下图中的代码,你会发现,threadLocal在初始化时返回的都是同一个对象a!
看一看ThreadLocal源码
我们直接看最常用的set操作:
你会看到,set需要首先获得当前线程对象Thread;
然后取出当前线程对象的成员变量ThreadLocalMap;
如果ThreadLocalMap存在,那么进行KEY/VALUE设置,KEY就是ThreadLocal;
如果ThreadLocalMap没有,那么创建一个;
说白了,当前线程中存在一个Map变量,KEY是ThreadLocal,VALUE是你设置的值。
看一下get操作:
这里其实揭示了ThreadLocalMap里面的数据存储结构,从上面的代码来看,ThreadLocalMap中存放的就是Entry,Entry的KEY就是ThreadLocal,VALUE就是值。
ThreadLocalMap.Entry:
弱引用?
在JAVA里面,存在强引用、弱引用、软引用、虚引用。这里主要谈一下强引用和弱引用。
强引用,就不必说了,类似于:
A a = new A();
B b = new B();
考虑这样的情况:
C c = new C(b);
b = null;
考虑下GC的情况。要知道b被置为null,那么是否意味着一段时间后GC工作可以回收b所分配的内存空间呢?答案是否定的,因为即便b被置为null,但是c仍然持有对b的引用,而且还是强引用,所以GC不会回收b原先所分配的空间!既不能回收利用,又不能使用,这就造成了内存泄露。
那么如何处理呢?
可以c = null;也可以使用弱引用!(WeakReference w = new WeakReference(b);)
分析到这里,我们可以得到:
这里我们思考一个问题:ThreadLocal使用到了弱引用,是否意味着不会存在内存泄露呢?
首先来说,如果把ThreadLocal置为null,那么意味着Heap中的ThreadLocal实例不再有强引用指向,只有弱引用存在,因此GC是可以回收这部分空间的,也就是key是可以回收的。但是value却存在一条从Current Thread过来的强引用链。因此只有当Current Thread销毁时,value才能得到释放。
因此,只要这个线程对象被gc回收,就不会出现内存泄露,但在threadLocal设为null和线程结束这段时间内不会被回收的,就发生了我们认为的内存泄露。最要命的是线程对象不被回收的情况,比如使用线程池的时候,线程结束是不会销毁的,再次使用的,就可能出现内存泄露。
那么如何有效的避免呢?
事实上,在ThreadLocalMap中的set/getEntry方法中,会对key为null(也即是ThreadLocal为null)进行判断,如果为null的话,那么是会对value置为null的。我们也可以通过调用ThreadLocal的remove方法进行释放!
好了,到这里,ThreadLocal的剖析就完成了,自己对ThreadLocal的认识又深入了些,^_^
手写系列相关爆文
【手写系列】写出我的第一个框架:迷你版Spring MVC
【手写系列】透彻理解Spring事务设计思想之手写实现
【手写系列】透彻理解MyBatis设计思想之手写实现
【手写系列】纯手写实现一个高可用的RPC
【手写系列】理解数据库连接池底层原理之手写实现
【手写系列】对HashMap的思考及手写实现
【手写系列】纯手写实现JDK动态代理
【手写系列】写一个迷你版的Tomcat
作者:张丰哲
链接:https://www.jianshu.com/p/ee8c9dccc953
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
对ThreadLocal实现原理的一点思考相关推荐
- [杂记]对RSA算法的数学原理的一点思考
转载于:https://www.cnblogs.com/CQBZOIer-zyy/p/9808041.html
- java.lang.ThreadLocal实现原理和源码分析
java.lang.ThreadLocal实现原理和源码分析 1.ThreadLocal的原理:为每一个线程维护变量的副本.某个线程修改的只是自己的副本. 2.ThreadLocal是如何做到把变量变 ...
- 对高并发流量控制的一点思考
前言 在实际项目中,曾经遭遇过线上5W+QPS的峰值,也在压测状态下经历过10W+QPS的大流量请求,本篇博客的话题主要就是自己对高并发流量控制的一点思考. 应对大流量的一些思路 首先,我们来说一下什 ...
- 贝特朗奇论 用计算机,关于贝特朗奇论的一点思考
关于贝特朗奇论的一点思考 贝特朗奇论这个名字就很奇怪,我最开始以为是贝特朗奇的某个论点或者命题,但是百度了一下发现原来是贝特朗(Bertrand)的"奇论",最初用以批判当时尚不严 ...
- 关于前端职业规划的一点思考
自己目前已经工作3年了,最近也刚换了新工作,日常也一直在考虑自己的前端职业规划到底是怎样的,目前个人视角还不是很宽广,怕误人子弟,以下这篇文章有点启发,故转发供大家借鉴(里面有部分内容做了一些小修改) ...
- ”杠铃“策略:关于市场的一点思考,从转债到股票量化投研
持续行动1期 46/100,"AI技术应用于量化投资研究". 第1期行动将近过半,进入一个"爬坡期". "低垂之果"基本上摘干净了,比如数据 ...
- 【模拟电路】对BJT的Ib为什么能控制Ic的一点思考和臆测
[模拟电路]对BJT的Ib为什么能控制Ic的一点思考和臆测 首先声明一下,本人并非专门研究模电.晶体管原理的学者,如有纰漏或勘误,还请大佬指正.轻喷. 这是我读<模拟电子技术基础>(第五版 ...
- 30岁成不了技术专家就应该转做管理?希望通过本文给大家带来一点思考
很多程序员都有一点技术情节,喜欢"专心搞技术",不喜欢管理,尤其管人.甚至为自己是"专注于技术"而自感清高,有点看不起那些"外行管理内行"或 ...
- mysql 手动写时间_关于数据库中如何存储时间的一点思考
1.切记不要用字符串存储日期 我记得我在大学的时候就这样干过,而且现在很多对数据库不太了解的新手也会这样干,可见,这种存储日期的方式的优点还是有的,就是简单直白,容易上手. 但是,这是不正确的做法,主 ...
最新文章
- 潘云鹤:人工智能走向2.0 | 全球青少年图灵计划首场大师公开课
- visual studio如何给源码文件添加header信息?(创建者,创建日期等)(License Header Manager插件)
- html除左侧浮动,html清除浮动的6种方法示例
- Java0steam_Java学习 - Stream 使用
- emlog-FLY主题模板1.4版本免费完全开源
- ISCW实验10:安装SDM到路由器的FLASH中
- 拳王虚拟项目公社:如何通过知识付费赚钱,知识付费搬运赚钱,虚拟资源付费项目
- html中img显示旋转,css如何实现图片的旋转展示效果(代码示例)
- 数据中心运维管理经验39条
- jvisualVm用法
- Applese 的毒气炸弹(最小生成树)
- 人类(行为)动力学(1)——初步了解
- lintcode-微软笔试
- 节目源php代理_【斗鱼直播源】浏览器抓取真实直播源地址(纯前端JS PHP解析源码)...
- react native 背景颜色渐变
- Laravel将Word文档转化为pdf文件
- U盘打不开的常见情况和解决方法
- asp.net 是什么?
- python对于字典d d.get(x、y)_python--字典
- 2021-11-26 WPF上位机 96-Modbus通信代码的封装
热门文章
- php中的foreach和js中的foreach的用法和区别
- 说一说限制字数的输入框踩的坑
- Codeforces Round #351 (VK Cup 2016 Round 3, Div. 2 Edition) A. Bear and Game 水题
- Yik-Chung Wu ---Time synchronization for wireless sensor networks
- 专接本微型计算机原理考试,河北省2009年专接本-微型计算机原理与汇编语言试卷...
- sql server 2008 r2 没有维护计划_坚果R2发布,骁龙865+1亿像素+90Hz,4499元起
- 购物车清除的php,php-如何清除废弃的woocommerce购物车
- linux下打开配置文件命令_Linux下用户权限相关命令
- NMF 非负矩阵分解
- makefile 基础用法