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

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。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值