ThreadLocal提供线程内部变量。ThreadLocal创建的变量只能被当前线程访问,其他线程则无法访问和修改。
当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
ThreadLocalMap是一个自定义的HashMap结构,只适用于维护线程本地值。
为了帮助处理非常大切长期使用的用法,hash table entry使用若引用作为key。
但是,因为没有引用队列,因此只有表开始空间不足时才能保证删除过时条目。
ThreadLocalMap使用若引用的原因在于,当没有强引用指向ThreadLocal变量时,它可被回收这样避免
ThreadLocal不能被回收而造成的内存泄漏的问题。但是,这里又可能出现另外一种内存泄漏的问题。
ThreadLocalMap 维护 ThreadLocal 变量与具体实例的映射,
当 ThreadLocal 变量被回收后,该映射的键变为 null,该 Entry 无法被移除。
从而使得实例被该 Entry 引用而无法被回收造成内存泄漏。
ThreadLocalMap的set方法,会将建为null的entry的值设置为null,从而使得该值可被回收。
Thread类中有一个threadLocals和inheritableThreadLocals,它们都是ThreadLocalMap类型的变量,
而ThreadLocalMap是一个定制化的HashMap,在默认情况下,每个线程中的这两个变量都为null,
只有当前线程第一次调用ThreadLocal的set或者get方法才会创建它们。ThreadLocal类型的本地变量存放在具体的线程内存空间中。
threadlocals是一个HashMap结构,其中key就是当前ThreadLocal的实例对象引用,value是通过set方法传递的值。
InheritableThreadLocal继承自ThreadLocal,可以访问在父线程中设置的本地变量。
InheritableThreadLocal的世界里,变量inheritableThreadLocals替代了threadlocals。
InheritableThreadLocal通过重写方法将本地变量保存到了具体线程的inheritableThreadLocals变量里面。
当父线程创建子线程时,构造函数会把父线程中inheritableThreadLocals变量里面的本地变量复制一份保存到子线程的inheritableThreadLocals变量里面。
ThreadLocal用来保存线程上下文信息,在任意需要的地方可以获取;线程安全的,不适用于共享对象的更新问题。
一个ThreadLocal只能存储一个Object对象,如果需要存储多个Object对象那么就需要多个ThreadLocal。
弱引用也是用来描述非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,该对象仅仅被弱引用关联,那么就会被回收。
当仅仅只有ThreadLocalMap中的Entry的key指向ThreadLocal的时候,ThreadLocal会进行回收的!!!
ThreadLocal定义为static还有一个好处就是,由于ThreadLocal有强引用在,那么在ThreadLocalMap里对应的Entry的键会永远存在,那么执行remove的时候就可以正确进行定位到并且删除!!!
Netty的核心设计就是将原生的Map结构替换为数组结构。每个FastThreadLocal对象生成一个全局唯一的index,并使用InternalThreadLocalMap中的数组通过index寻址,这样就直接解决了哈希冲突的问题。
小结
1:ThreadLocal是线程执行时的上下文,用于存放线程局部变量。它不能解决并发情况下数据共享的问题
2:ThreadLocal是以ThreadLocal对象本身作为key的,不是线程(Thread)对象
3:ThreadLocal存在内存泄露的风险,要养成用完即删的习惯
4:ThreadLocal使用散列定位数据存储坐标,如果发生碰撞,使用线性探测重新定位,这在高并发场景下会影响一点性能。改善方法如netty的FastThreadLocal,使用固定坐标,以空间换时间,后面会分析FastThreadLocal实现。
参考文献
https://www.kancloud.cn/ssj234/netty-source/438383
https://blog.verysu.com/mobile/article/403
https://blog.csdn.net/zhousenshan/article/details/82942145
https://www.cnblogs.com/stevenczp/p/7667719.html
https://segmentfault.com/a/1190000012926809
并发五: 透过源码彻底理解ThreadLocal
网友评论