并發(fā)編程(六)—— ThreadLocal

一逊笆、ThreadLocal簡介

? ? ? ? 多線程訪問同一個共享變量時經(jīng)常容易產(chǎn)生并發(fā)問題,為了保證線程安全岂傲,就需要一定的同步機(jī)制难裆,除了常見的加鎖處理以外,JDK還提供了ThreadLocal镊掖,即本地變量副本乃戈。當(dāng)創(chuàng)建了一個ThreadLocal變量,那么訪問這個變量的每一個線程都會有該變量的一個本地副本堰乔,當(dāng)多個線程操作該變量時偏化,實(shí)際操作的是自己的本地內(nèi)存中保存的變量脐恩,從而避免了線程安全問題镐侯。

圖 1-1

二、ThreadLocal使用示例

? ? ? ? 示例代碼:

圖 2-1 示例代碼
圖 2-2 運(yùn)行結(jié)果

? ? ? ? 從運(yùn)行結(jié)果可以看出threadA和threadB調(diào)用的ThreadLocal.set設(shè)置的是線程本地內(nèi)存中的一個副本,這個副本在線程間是隔離的苟翻,彼此不可見韵卤。

三、ThreadLocal實(shí)現(xiàn)原理

? ? ? ? 從Thread源碼中可以看到崇猫,Thread有兩個變量threadLocals和inheritableThreadLocals沈条,而且都是ThreadLocal.ThreadLocalMap類型的變量:

圖 3-1 Thread部分源碼

? ? ? ? 即每個Thread都包含自己的ThreadLocalMap:

圖 3-2 線程與ThreadLocalMap

? ? ? ? 由ThreadLocalMap可以發(fā)現(xiàn),ThreadLocalMap是ThreadLocal的靜態(tài)內(nèi)部類诅炉,真正起到保存線程私有數(shù)據(jù)的正是這個ThreadLocalMap蜡歹,而ThreadLocal只是在外面包了一層,對外提供統(tǒng)一入口涕烧,下面分析一下ThreadLocalMap的源碼:

圖 3-3 ThreadLocalMap部分源碼

? ? ? ? 可以發(fā)現(xiàn)ThreadLocalMap當(dāng)中有一個名為table的Entry類型的數(shù)組月而,且Entry的鍵是ThreadLocal的弱引用(WeakReference)。而ThreadLocalMap的初始化议纯,實(shí)際上是對Entry數(shù)組的初始化:

圖 3-4 ThreadLocalMap部分源碼

? ? ? ? 到這里大概就猜測到ThreadLocal對各自線程本地變量副本的操作實(shí)際上是對ThreadLocalMap的操作父款,我們驗(yàn)證一下,看幾個ThreadLocal常用的api:

? ? ? ? (1)ThreadLocal.get

圖 3-5 ThreadLocal.get 源碼

? ? ? ? ? ?ThreadLocal中的get方法瞻凤,首先會獲取當(dāng)前線程的ThreadLocalMap憨攒,以ThreadLocal本身作為key去ThreadLocalMap中查找,如果存在不為空Entry阀参,就返回Entry.value肝集,否則就會初始化ThreadLocalMap并返回初始化后的默認(rèn)值,初始化源碼如下:

圖 3-6 ThreadLocalMap初始化源碼

? ? ? ? (2)ThreadLocal.set

圖 3-7 ThreadLocal.set源碼

? ? ? ? 先獲取當(dāng)前線程蛛壳,并取出當(dāng)前線程的ThreadLocalMap包晰,如果ThreadLocalMap不為空,則直接以key為ThreadLocal引用為鍵炕吸,value為關(guān)聯(lián)值進(jìn)行存儲伐憾;如果ThreadLocalMap為空,則會先創(chuàng)建ThreadLocalMap再進(jìn)行存儲赫模。

? ? ? ? (3)ThreadLocal.remove

圖 3-8 ThreadLocal.remove源碼

? ? ? ? 先根據(jù)當(dāng)前線程獲取到該線程的TreadLocalMap树肃,如果ThreadLocalMap存在,就調(diào)用ThreadLocalMap.remove方法刪除當(dāng)前線程中指定的ThreadLocal實(shí)例的本地變量瀑罗。

? ? ? ? 綜上胸嘴,可以得出ThreadLocal存儲的數(shù)據(jù)結(jié)構(gòu):

圖 3-9 ThreadLocal

四、ThreadLocal內(nèi)存泄露問題

? ? ? ? ThreadLocalMap是Thread類的成員變量斩祭,Thread銷毀時劣像,ThreadLocalMap也會隨之銷毀,即ThreadLocalMap的生命周期與Thread綁定摧玫。而ThreadLocalMap內(nèi)部維護(hù)了一個Enrty數(shù)組耳奕,而Entry數(shù)組的鍵為ThreadLocal的弱引用,弱引用的特點(diǎn)是食铐,JVM將會在下一次GC的時候清理掉弱引用丐谋,而ThreadLocalMap的value為對象的強(qiáng)引用,且ThreadLocalMap生命周期與Thread相同奈懒,當(dāng)GC發(fā)生時芍躏,會出現(xiàn)key被清理邪乍,而value還存活的情況,導(dǎo)致value無法訪問到对竣,無法被回收庇楞,此時就會發(fā)生內(nèi)存泄露。

圖 4-1 ThreadLocal引用關(guān)系

強(qiáng)否纬、軟姐刁、弱、虛引用內(nèi)容可以參考深入理解Java虛擬機(jī)(三)—— 垃圾收集器與內(nèi)存分配策略

? ? ? ? 解決辦法:在將ThreadLocal設(shè)置為空前烦味,執(zhí)行remove方法聂使,將key為空的鍵值對也清空。

? ? ? ??

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末谬俄,一起剝皮案震驚了整個濱河市柏靶,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌溃论,老刑警劉巖屎蜓,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異钥勋,居然都是意外死亡炬转,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進(jìn)店門算灸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來扼劈,“玉大人,你說我怎么就攤上這事菲驴〖龀常” “怎么了?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵赊瞬,是天一觀的道長先煎。 經(jīng)常有香客問我,道長巧涧,這世上最難降的妖魔是什么薯蝎? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮谤绳,結(jié)果婚禮上占锯,老公的妹妹穿的比我還像新娘袒哥。我一直安慰自己,他們只是感情好烟央,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布统诺。 她就那樣靜靜地躺著歪脏,像睡著了一般疑俭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上婿失,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天钞艇,我揣著相機(jī)與錄音,去河邊找鬼豪硅。 笑死哩照,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的懒浮。 我是一名探鬼主播飘弧,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼砚著!你這毒婦竟也來了次伶?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤稽穆,失蹤者是張志新(化名)和其女友劉穎冠王,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體舌镶,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡柱彻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了餐胀。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片哟楷。...
    茶點(diǎn)故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖否灾,靈堂內(nèi)的尸體忽然破棺而出吓蘑,到底是詐尸還是另有隱情,我是刑警寧澤坟冲,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布磨镶,位于F島的核電站,受9級特大地震影響健提,放射性物質(zhì)發(fā)生泄漏琳猫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一私痹、第九天 我趴在偏房一處隱蔽的房頂上張望脐嫂。 院中可真熱鬧统刮,春花似錦、人聲如沸账千。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽匀奏。三九已至鞭衩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間娃善,已是汗流浹背论衍。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留聚磺,地道東北人坯台。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像瘫寝,于是被迫代替她去往敵國和親蜒蕾。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容