ThreadLocal原理总结

一:ThreadLocal是什么?

ThreadLocal,即线程本地变量。一个共享变量存进该容器相当于在线程内部拷贝了一个副本ThreadLocal里面的变量都是存在当前线程的。当操作ThreadLocal里面的变量时,实际操作的是存在自己线程的那个变量副本,该变量副本对于每一个线程都是独立的,从而实现了变量的隔离性,保证了线程安全。

二:ThreadLocal保证线程变量隔离性的原理

每一个Thread线程都会拥有自己的一个成员变量ThreadLocalMap,该变量默认为空(实际是ThreadLocal的静态内部类,只是Thread持有引用)。当往ThreadLocal存数据时,调用的是ThreadLocal的set方法,该方法先拿到当前线程的ThreadLocalMap,然后以当前threadLocal实例为key把数据存进该map中。当取数据时,一样拿到当前线程的ThreadLocalMap,并以当前threadLocal实例为key从里面拿出数据。

//Thread类的成员变量ThreadLocalMap

//ThreadLocal的set方法:先拿到当前线程的ThreadLocalMap实例,然后往该map上存数据

 ThreadLocal原理总结_第1张图片

//ThreadLocal的get方法:先拿到当前线程的ThreadLocalMap实例,然后往该map上取数据

ThreadLocal原理总结_第2张图片

//ThreadLocal类的getMap方法,实际返回的是线程的ThreadLocalMap实例

简而言之,存进ThreadLocal的数据,相当于存进了线程自己的变量中。因此如果要保证共享变量的隔离性,就把他放进ThreadLocal(相当于在线程中拷贝了一份),要用时,从ThreadLocal中拿出来即可(拿出当前线程的副本)

注意:保证的是隔离性!!!不是同步性!!!

三:ThreadLocalMap

ThreadLocalMap的设计类似于HashMap,一样是通过Entry节点来存数据,一样是双边集合,不过该Entry与HashMap中的Entry不一样。前者是ThreadLocalMap的静态内部类,后者是Map的内部接口(实现类是Node)。另外,ThreadLocalMap的Entry内部类,key默认是当前threadLocal对象

//ThreadLocalMap的set方法,key是this当前对象,也就是ThradLocal实例

ThreadLocal原理总结_第3张图片

        注意:该Entry是弱引用的子类,会把key设置成弱引用。也就是可能出现key被删除,但是value还在的情况,从而造成内存泄漏。因此,尽量使用完就通过remove()方法把value移除

//Entry继承了WeakReference,然后在构造方法中调用super(k),即设置key为弱引用

(经典用法----通过一个类去继承WeakReference,然后调用父类的构造方法,把某个对象设置成弱引用)

ThreadLocal原理总结_第4张图片

不懂就问:在外部通过new关键字创建一个threadLocal实例,那么该threadLocal实例不就是强引用吗?那么Entry即使把该threadLocal实例设置成弱引用,threadLocal也会被回收吗?

------------------------------------------------------------------------------------------------------------------------

追更:

上面的不懂就问中:

如果threadLocal是一个类的成员变量的话,由于是强引用(上面提到的new),且threadLocal引用变量也位于堆区,所以不会被回收,也就是说,Entry中设置成弱引用,是起不了什么作用的。此时如果要避免内存泄漏,需要threadLocal.remove(),所以如果是成员变量,一般设置成static,防止创建多个,浪费内存。

如果theadLocal是一个局部变量的话,threadLocal的引用是位于栈区的。则当方法走完后,threadLocal的引用被销毁了,此时Entry中把threadLocal设置成弱引用,则threadLocal会随垃圾回收而回收。Entry中key被回收后,value由于是强引用(value是直接赋值的),所以不会被回收。但是当其他theadLocal调用get或者set等方法时(源码中有展示),会被清理掉。

staleSlot意为陈旧的槽,实际就是key==nullEntry

ThreadLocal原理总结_第5张图片

至于为什么value不设置成弱引用,是因为如果设置成弱引用,垃圾回收后,key可能还在(以成员变量存在的时候),但是value没了,从而造成数据丢失。

ThreadLocal原理总结_第6张图片

 

最后:附上后端技术交流圈,欢迎各位大佬入圈交流技术......V:ff1341658(先添加好友后拉群,添加好友时请备注:小白不黑)

你可能感兴趣的:(总结笔记,线程,ThreadLocal,线程变量隔离)