ThreadLocal的作用
当多个线程同时读写同一共享变量时存在并发问题,如下图所示:
如果不共享上图红色的资源,不就没有并发问题了。
也就是说:一个线程存一个自己的变量,类比原来好几个人玩同一个球,现在一个人一个球,那就没有并发问题了。
ThreadLocal原理
如何把变量存在线程上呢?如何把线程的数据隔离呢?下面我们继续详解ThreadLocal的原理。
因为一个线程内,可以存在多个 ThreadLocal 对象,所以其实是ThreadLocal内部维护了一个 Map 。
这个 Map 不是直接使用 HashMap ,而是 ThreadLocal 实现的一个叫做 ThreadLocalMap 的静态内部类,用来存变量。
它的大概结构如下图所示:
ThreadLocalMap是一个Map,key是ThreadLocal,value是Object。
映射到源码就是如下所示:
往ThreadLocalMap里面放值
从ThreadLocalMap里面取值
实际上,ThreadLocalMap内部持有一个 Entry[] 类型的数组 table,每个数组成员都是一个键值对,Entry数组是真正承载数据的地方。
Entry继承自WeakReference,每个Entry 的 key 都是一个 ThreadLocal 对象的弱引用,value 是Object 类型,是强引用,ThreadLocalMap 中可以包含多个ThreadLocal对象。
如下图所示:
那么如果一个线程使用多个ThreadLocal对象,ThreadLocalMap如何区分不同的ThreadLocal呢?
实际上,每一个ThreadLocal对象都包含了一个独一无二的threadLocalHashCode值,使用这个值就可以在KV数组中找到对应的本地变量。
不过需要注意的是,虽然key值是弱引用,不影响ThreadLocal对象回收,但value值是强引用。
当ThreadLocal被回收,value对象不会被回收,记得要调用 remove() 方法避免内存泄露。
陈睿mikechen
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》