当前位置:   article > 正文

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

threadlocal可见性

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。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/294510
推荐阅读
相关标签
  

闽ICP备14008679号