对ThreadLocal实现原理的一点思考
前言
在《透徹理解Spring事務設計思想之手寫實現》中,已經向大家揭示了Spring就是利用ThreadLocal來實現一個線程中的Connection是同一個,從而保證了事務。本篇博客將帶大家來深入分析ThreadLocal的實現原理。
?
ThreadLocal是什么、有什么、能做什么?
ThreadLocal提供一個線程(Thread)局部變量,訪問到某個變量的每一個線程都擁有自己的局部變量。說白了,ThreadLocal就是想在多線程環境下去保證成員變量的安全。
ThreadLocal提供的方法
ThreadLocal API對于ThreadLocal而言,常用的方法,就是get/set/initialValue方法。
我們先來看一個例子
demo運行結果
是你想象中的結果么??
很顯然,在這里,并沒有通過ThreadLocal達到線程隔離的機制,可是ThreadLocal不是保證線程安全的么?這是什么鬼?
雖然,ThreadLocal讓訪問某個變量的線程都擁有自己的局部變量,但是如果這個局部變量都指向同一個對象呢?這個時候ThreadLocal就失效了。仔細觀察下圖中的代碼,你會發現,threadLocal在初始化時返回的都是同一個對象a!
?
看一看ThreadLocal源碼
我們直接看最常用的set操作:
set?
線程局部變量?
createMap你會看到,set需要首先獲得當前線程對象Thread;
然后取出當前線程對象的成員變量ThreadLocalMap;
如果ThreadLocalMap存在,那么進行KEY/VALUE設置,KEY就是ThreadLocal;
如果ThreadLocalMap沒有,那么創建一個;
說白了,當前線程中存在一個Map變量,KEY是ThreadLocal,VALUE是你設置的值。
看一下get操作:
get這里其實揭示了ThreadLocalMap里面的數據存儲結構,從上面的代碼來看,ThreadLocalMap中存放的就是Entry,Entry的KEY就是ThreadLocal,VALUE就是值。
ThreadLocalMap.Entry:
弱引用?
在JAVA里面,存在強引用、弱引用、軟引用、虛引用。這里主要談一下強引用和弱引用。
強引用,就不必說了,類似于:
A a = new A();
B b = new B();
考慮這樣的情況:
C c = new C(b);
b = null;
考慮下GC的情況。要知道b被置為null,那么是否意味著一段時間后GC工作可以回收b所分配的內存空間呢?答案是否定的,因為即便b被置為null,但是c仍然持有對b的引用,而且還是強引用,所以GC不會回收b原先所分配的空間!既不能回收利用,又不能使用,這就造成了內存泄露。
那么如何處理呢?
可以c = null;也可以使用弱引用!(WeakReference w = new WeakReference(b);)
分析到這里,我們可以得到:
內存結構圖這里我們思考一個問題:ThreadLocal使用到了弱引用,是否意味著不會存在內存泄露呢?
首先來說,如果把ThreadLocal置為null,那么意味著Heap中的ThreadLocal實例不再有強引用指向,只有弱引用存在,因此GC是可以回收這部分空間的,也就是key是可以回收的。但是value卻存在一條從Current Thread過來的強引用鏈。因此只有當Current Thread銷毀時,value才能得到釋放。
因此,只要這個線程對象被gc回收,就不會出現內存泄露,但在threadLocal設為null和線程結束這段時間內不會被回收的,就發生了我們認為的內存泄露。最要命的是線程對象不被回收的情況,比如使用線程池的時候,線程結束是不會銷毀的,再次使用的,就可能出現內存泄露。
那么如何有效的避免呢?
事實上,在ThreadLocalMap中的set/getEntry方法中,會對key為null(也即是ThreadLocal為null)進行判斷,如果為null的話,那么是會對value置為null的。我們也可以通過調用ThreadLocal的remove方法進行釋放!
?
好了,到這里,ThreadLocal的剖析就完成了,自己對ThreadLocal的認識又深入了些,^_^
?
手寫系列相關爆文
【手寫系列】寫出我的第一個框架:迷你版Spring MVC
【手寫系列】透徹理解Spring事務設計思想之手寫實現
【手寫系列】透徹理解MyBatis設計思想之手寫實現
【手寫系列】純手寫實現一個高可用的RPC
【手寫系列】理解數據庫連接池底層原理之手寫實現
【手寫系列】對HashMap的思考及手寫實現
【手寫系列】純手寫實現JDK動態代理
【手寫系列】寫一個迷你版的Tomcat
作者:張豐哲
鏈接:https://www.jianshu.com/p/ee8c9dccc953
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權并注明出處。
總結
以上是生活随笔為你收集整理的对ThreadLocal实现原理的一点思考的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【手写系列】写一个迷你版的Tomcat
- 下一篇: Linux 还能这么玩,10 个非常有趣