ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

ThreadLocal怎么实现线程隔离的?可见性问题?为什么要重新定义一个threadLocalHashCode?为什么有内存泄露?弱引用又是什么?

2021-06-05 17:59:33  阅读:188  来源: 互联网

标签:threadLocalHashCode ThreadLocalMap get ThreadLocal 线程 引用 key


1. ThreadLocal实现线程隔离的使用场景

线程1的if代码块要执行的话,那么flag.get()的值必须是false;同理线程2的if代码块要执行的话,flag.get()的值必须是true。也就是说线程1要得到线程2对flag变量操作的值,线程2要得到线程1操作的值。最终没有任何结果输出,说明两个线程没有得到对方修改的内容

有些小伙伴就说了,各自线程得不到对方操作的内容不是很正常吗?这就是可见性问题啊。确实,由于共享数据存在可见性问题,线程间的数据不能得到很好的同步,也会出现上述场景。那我设计了如下代码,证明了:即使有可见性问题,仍然存在一个线程读取到其它线程操作内容的情况

因此,我们可以确定ThreadLocal的数据是实现线程隔离的,而且它的目的就是让各个线程之间不可见

 

2. ThreadLocal怎么实现线程隔离

2.1 首先,ThreadLocal对象只给我们提供了三个方法,set、get和remove,那接下来对这三个方法分析一下。

2.2 set方法,赋值是将数据保存到各个线程的ThreadLocalMap中,从而实现线程隔离

2.3 ThreadLocalMap的set方法实现——ThreadLocal对象为什么要重新定义threadLocalHashCode

2.4 get方法比较简单

2.5 remove()方法——防止内存泄露

网上都说ThreadLocal存在内存泄露,这到底是怎么回事呢?对于一个ThreadLocal来说,它是作为key放在ThreadLocalMap中的,当这个ThreadLocal对象结束了生命,那么它应该被回收。但由于ThreadLocalMap是线程属性,生命周期和线程一样长;线程还未结束时ThreadLocalMap自然有ThreadLocal对象的引用,ThreadLocal也就无法被回收了。于是,开发者将ThreadLocal和ThreadLocalMap之间的引用改为弱引用,Entry不再是一般的键值对,而只有一个value属性,key通过一种弱引用形式表现。这样当ThreadLocal没有了强引用,只有ThreadLocalMap的弱引用,ThreadLocal会被回收。

但是这边又出现了一个问题,虽然Entry的key使用了弱引用,ThreadLocal对象可以被回收。但是Entry的value再也无法通过key访问了,无法回收,value还是存在内存泄露。所以一般在使用ThreadLocal结束后,要调用remove方法,去除key的引用,同时将value值置为null。

标签:threadLocalHashCode,ThreadLocalMap,get,ThreadLocal,线程,引用,key
来源: https://blog.csdn.net/yldmkx/article/details/117594525

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有