Treadlocal執行緒安全與弱引用問題

2021-09-29 10:54:39 字數 1533 閱讀 9967

參見 : 

1、在threadlocal的生命週期中,都存在這些引用。看下圖: 實線代表強引用,虛線代表弱引用。

2、threadlocal的實現是這樣的:每個thread 維護乙個 threadlocalmap 對映表,這個對映表的 key 是 threadlocal例項本身,value 是真正需要儲存的 object。

3、也就是說 threadlocal 本身並不儲存值,它只是作為乙個 key 來讓執行緒從 threadlocalmap 獲取 value。值得注意的是圖中的虛線,表示 threadlocalmap 是使用 threadlocal 的弱引用作為 key 的,弱引用的物件在 gc 時會被**。

4、threadlocalmap使用threadlocal的弱引用作為key,如果乙個threadlocal沒有外部強引用來引用它,那麼系統 gc 的時候,這個threadlocal勢必會被**,這樣一來,threadlocalmap中就會出現key為null的entry,就沒有辦法訪問這些key為null的entry的value,如果當前執行緒再遲遲不結束的話,這些key為null的entry的value就會一直存在一條強引用鏈:thread ref -> thread -> threalocalmap -> entry -> value永遠無法**,造成記憶體洩漏。

5、總的來說就是,threadlocal裡面使用了乙個存在弱引用的map, map的型別是threadlocal.threadlocalmap.map中的key為乙個threadlocal例項。這個map的確使用了弱引用,不過弱引用只是針對key。每個key都弱引用指向threadlocal。 當把threadlocal例項置為null以後,沒有任何強引用指向threadlocal例項,所以threadlocal將會被gc**。

但是,我們的value卻不能**,而這塊value永遠不會被訪問到了,所以存在著記憶體洩露。因為存在一條從current thread連線過來的強引用。只有當前thread結束以後,current thread就不會存在棧中,強引用斷開,current thread、map value將全部被gc**。最好的做法是將呼叫threadlocal的remove方法,這也是等會後邊要說的。

6、其實,threadlocalmap的設計中已經考慮到這種情況,也加上了一些防護措施:在threadlocal的get(),set(),remove()的時候都會清除執行緒threadlocalmap裡所有key為null的value。這一點在上一節中也講到過!

7、但是這些被動的預防措施並不能保證不會記憶體洩漏:

(1)使用static的threadlocal,延長了threadlocal的生命週期,可能導致記憶體洩漏。

(2)分配使用了threadlocal又不再呼叫get(),set(),remove()方法,那麼就會導致記憶體洩漏,因為這塊記憶體一直存在。

總結:threadlocal不是絕對執行緒安全

1.如果執行緒結束後不銷毀, 非常大概率出現執行緒安全問題

2.如果執行緒結束後銷毀,應該不會出現執行緒安全問題

執行緒安全與執行緒不安全

執行緒安全是針對多執行緒來講的,如果所使用的公用變數在多執行緒下沒有被保護機制時,變數結果會和理論值不一致,這樣就叫作執行緒不安全,相反公用變數在保護機制下工作,就不會出現 隨機 變化,這時叫執行緒安全。執行緒安全 在多執行緒中使用時,不用自已做同步處理.執行緒不安全 在多執行緒中使用時,必須做執行...

執行緒安全與執行緒不安全

執行緒安全是針對多執行緒來講的,如果所使用的公用變數在多執行緒下沒有被保護機制時,變數結果會和理論值不一致,這樣就叫作執行緒不安全,相反公用變數在保護機制下工作,就不會出現 隨機 變化,這時叫執行緒安全。執行緒安全 在多執行緒中使用時,不用自已做同步處理.執行緒不安全 在多執行緒中使用時,必須做執行...

執行緒安全與執行緒不安全

執行緒不安全 就是不提供資料訪問保護,在多執行緒環境中對資料進行修改,會出現資料不一致的情況。執行緒安全 就是多執行緒環境中有對全域性變數的變動時,需要對執行的 塊採用鎖機制,當乙個執行緒訪問到某個資料時,其他執行緒需要等待當前執行緒執行完該 塊才可執行,不會出現資料不一致或者資料被汙染。如果一段 ...