當前位置:
首頁 > 最新 > ThreadLocal實現原理詳解

ThreadLocal實現原理詳解

簡書 滌生。轉載請註明原創出處,謝謝!如果讀完覺得有收穫的話,歡迎關注公共號,更多分享等著你。

介紹

ThreadLocal大家應該不陌生,經常在一些同步優化中會使用到它。很多地方叫線程本地變數,ThreadLocal為變數在每個線程中都創建了一個副本,那麼每個線程可以訪問自己內部的副本變數。也就是對於同一個ThreadLocal,每個線程通過get、set、remove介面操作只會影響自身線程的數據,不會干擾其他線程中的數據。

ThreadLocal是怎麼實現的呢?

ThreadLocal又有哪些誤區呢?

源碼分析

從ThreadLocal的set方法說起,set是用來設置想要在線程本地數據,可以看到先拿到當前線程,然後獲取當前線程的ThreadLocalMap,如果map不存在先創建map,然後設置本地變數值。

那ThreadLocalMap又是什麼?跟線程有什麼關係?可以看到ThreadLocalMap其實是線程自身的一個成員屬性threadLocals的類型。也就是線程本地數據都存在這個threadLocals應用的ThreadLocalMap中。

我們再接著看看ThreadLocalMap,跟想像中的Map有點不一樣,它其實內部是有個Entry數組,將數據包裝成靜態內部類Entry對象,存儲在這個table數組中,數組的下標是threadLocal的threadLocalHashCode&(INITIAL_CAPACITY-1),因為數組的大小是2的n次方,那其實這個值就是threadLocalHashCode%table.length,用&而不用%,其實是提升效率。只要數組的大小不變,這個索引下標是不變的,這也方便去set和get數據。

我們再看看Entry的定義,Entry繼承自WeakReference(這麼做目的是什麼,後面會講到),構造方法有兩個參數一個是threadLocal對象,一個是線程本地的變數。

看到這裡大家應該就明白了,每個線程自身都維護著一個ThreadLocalMap,用來存儲線程本地的數據,可以簡單理解成ThreadLocalMap的key是ThreadLocal變數,value是線程本地的數據。就這樣很簡單的實現了線程本地數據存儲以及交互訪問。

誤區

上文也提到了,Entry繼承自WeakReference,大家都知道WeakReference(弱引用)的特性,只要從根集出發的引用中沒有有效引用指向該對象,則該對象就可以被回收,這裡的有效引用並不包含WeakReference,所以弱引用不影響對象被GC。這裡被WeakReference引用的對象是哪個呢?可以看Entry的構造方法,很容易看出指的是ThreadLocal自身,也就是說ThreadLocal自身的回收不受ThreadLocalMap的這個弱引用的影響,讓用戶減輕GC的煩惱。

但是不用做些什麼嗎?這麼簡單?其實不然,ThreadLocalMap還做了其他的工作,試想一下,ThreadLocal對象如果外界沒有有效引用,是能夠被GC,但是Entry呢?Entry也能自動被GC嗎,當然不行,Entry還被ThreadLocalMap的table數組強引用著呢。所以ThreadLocalMap該做點什麼?我看看ThreadLocalMap的expungeStaleEntry這個方法,這個方法在ThreadLocalMap get、set、remove、rehash等方法都會調用到,看下面標紅的兩處代碼,第一處是將remove的entry賦空,第二次處是找到已經被GC的ThreadLocal,然後會清理掉table數組對entry的引用。這樣entry在後續的GC中就會被回收。

是不是這樣就萬事大吉了呢,不用擔心GC問題了呢?沒那麼簡單,還是有點坑:這裡的坑與WeakHashMap垃圾回收原理中所說的類似,如果數據初始化好之後,一直不調用get、set等方法,這樣Entry就一直不能回收,導致內存泄漏。所以一旦數據不使用最好主動remove。

有些同學問,如果線程資源回收了,還會泄漏嗎?當然不會,線程回收後,存在線程相關的ThreadLocalMap也會被回收,線程相關的本地數據自然也會回收。但是不要忘記ThreadLocal的使用場景,就是用來存儲線程本地變數,大部分場景中,線程都是一直存活或者長時間存活。

場景

一般在連接池優化上會使用到ThreadLocal,在多線程獲取連接池時,會有同步操作,影響性能。如果使用ThreadLocal,每個線程使用自己的獨立連接,性能會有一定的提升。

總結

希望這遍文章能夠提升大家對ThreadLocal的理解,避免踩坑,使用起來也更加瞭然於胸。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 滌生YinQi 的精彩文章:

TAG:滌生YinQi |