并发-ThreadLocal

1. 介绍

1.1 作用

ThreadLocal的作用主要是做数据隔离,填充的数据只属于当前线程,变量的数据对别的线程而言是相对隔离的。

1.2 原理

每个线程创建时会拥有一个Thread对象,该线程首次调用ThreaLocal.set()方法时,会创建ThreadLocalMap(这不同于HashMap,该Map由一个数组组成),利用线性检测(根据初始key的hashcode值确定元素在table数组中的位置,如果发现这个位置上已经有其他key值的元素被占用,则利用固定的算法寻找一定步长的下个位置,依次判断,直至找到能够存放的位置)解决Hash冲突问题。table数组中每个元素由entry组成,key为弱引用。

1.3 问题

1.3.1 内存泄漏

(1)什么是内存泄漏

在Java中,内存泄漏就是存在一些被分配的对象,这些对象有下面两个特点,首先,这些对象是可达的,即在有向图中,存在通路可以与其相连;其次,这些对象是无用的,即程序以后不会再使用这些对象。如果对象满足这两个条件,这些对象就可以判定为Java中的内存泄漏,这些对象不会被GC所回收,然而它却占用内存。

(2)为什么会内存泄露

线程的生命周期很长,当ThreadLocal没有被外部强引用的时候就会被GC回收(给ThreadLocal置空了):ThreadLocalMap会出现一个keynullEntry,但这个Entryvalue将永远没办法被访问到(后续在也无法操作set、get等方法了)。如果当这个线程一直没有结束,那这个keynullEntry因为也存在强引用(Entry.value),而Entry被当前线程的ThreadLocalMap强引用(Entry[] table),导致这个Entry.value永远无法被GC,造成内存泄漏。

(3)如何解决

及时调用ThreadLocal.remove()。

1.3.2 父子之间线程的变量传递丢失

InheritableThreadLocal提供了一种父子线程之间的数据共享机制。可以解决这个问题。但是InheritableThreadLocal和线程池使用的时候就会存在问题,因为子线程只有在线程对象创建的时候才会把父线程inheritableThreadLocals中的数据复制到自己的inheritableThreadLocals中。这样就实现了父线程和子线程的上下文传递。但是线程池的话,线程会复用,所以会存在问题。可以参考下阿里巴巴的transmittable-thread-local

2. 源码

3. 实践

4. FAQ

5. 参考资料

面试官问我ThreadLocal,我一口气给他说了四种

还不理解ThreadLocal?那是你还没读到这篇文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值