ThreadLocal造成的記憶體洩漏

2021-10-07 21:11:53 字數 1035 閱讀 2335

在多執行緒中為了避免執行緒安全問題,常用的一種方式就是引入threadlocal變數,為何這種方式會引發執行緒安全問題呢?

首先我們來看一下threadlocal是如何實現儲存執行緒私有變數的原理:

threadlocal裡面定義了乙個內部類threadlocalmap

static class threadlocalmap }

.... }

這個threadlocalmap是關鍵,再檢視thread原始碼,我們可以看到

每個thread持有乙個初始值為null的threadlocalmap變數

在threadlocal變數呼叫get、set方法時,會對當前執行緒的threadlocalmap進行初始化,那麼這時會做什麼操作呢

void createmap(thread t, t firstvalue)

threadlocalmap(threadlocal> firstkey, object firstvalue)

可以看到threadlocal變數將自身作為引數構造了執行緒持有的threadlocalmap,而這裡面初始化了乙個entry陣列型別的table,並且threadlocal變數是作為key使用的。是不是有點眼熟,不過這個entry是threadlocalmap裡的乙個內部類entry,從上面原始碼中可以看到entry繼承了weakreference,這是造成記憶體洩漏的關鍵。weakreference指的弱引用,弱引用的定義是,當jvm執行記憶體**時發現該某個物件只有弱引用時,會被**。那麼問題來了,當某個生存周期長的執行緒執行過程中,某個定義的threadlocal強引用變成了null,只剩執行緒裡的threadlocalmap裡持有的弱引用,gc發生時,該entry的key指向的物件將被**,可是強引用value指向的物件是無法**的,就造成了記憶體洩漏。

解決方法:當某個threadlocal變數不再使用時,記得threadlocal.remove(),刪除該key。

ThreadLocal 執行緒內取不到值

threadlocal 執行緒內取不到值 在 裡,從 request 請求裡拿出了一些資料例如使用者id啥的,儲存到了 threadlocal 裡,在後面具體的業務處理中,從 threadlocal 卻裡取不到值 大概率是因為當前業務執行緒和之前 不是同一執行緒,可以使用一下方法檢視一下執行緒 id...

執行緒範圍內共享資料ThreadLocal

原始碼 private t setinitialvalue 1 原始版本 public class threadlocaltestbefore start new thread new runnable start a b類分別為使用執行緒區域性變數的資料 static class a static...

關於threadlocal的來龍去脈

對tls更簡單的,但是更直觀的理解可以如下 基於c語言 1.全域性物件,全域性變數的作用域和生命週期是全域性的,這裡的全域性是指程序範疇,也就是說,如果你將其設計為全域性物件,全域性變數,就意味著你希望在多執行緒的環境中,仍然能共享和訪問。全域性物件,全域性變數不是說不讓多執行緒來訪問,而是說有的時...