ThreadLocal是怎樣煉成的

2021-07-28 00:01:32 字數 2317 閱讀 6437

好久沒更新部落格了,一直都有學習新知識,但是沒時間總結,主要因為顧著去發展模型興趣去了哈

難得靜下來寫一篇部落格

閒話不多說,直接進入主題

threadlocal是解決執行緒安全問題乙個很好的思路,threadlocal類中有乙個map,用於儲存每乙個執行緒的變數副本,map中元素的鍵為執行緒物件,而值對應執行緒的變數副本,由於key值不可重複,每乙個「執行緒物件」對應執行緒的「變數副本」,而到達了執行緒安全。

下面我們來剖析一下

首先我們要介紹一種儲存模式

這種模式是為了解決多執行緒變數共享導致執行緒安全和死鎖問題,首先看看下面的示意圖

objectx類會被多個執行緒使用到,為了避免執行緒安全以及可能的死鎖為題,我們希望每個執行緒都有自己的objectx例項。

於是我們設計出乙個**類,用來**儲存和獲取操作。

實際上jdk已經提供了上述模式的實現,那就是今天的豬腳threadlocal

首先看乙個簡單的threadlocal例子

public

class

threadspecificdateformat

};public

static date parse(string timestamp, string format) throws parseexception

public

static string format(date date, string format)

}

結合上圖看,例項的統一接入點就是threadlocal.get()(ts_sdf.get())這個方法了,通過這個接入點客戶端就能拿到object例項。

接下來再看看get方法的具體實現

public t get() 

}return setinitialvalue();

}threadlocalmap getmap(thread t)

第一步 先獲通過thread.currentthread()取當前執行緒

第二步 然後獲取當前執行緒的threadlocals屬性

第三步 在threadlocals屬性裡獲取entry例項

第四部 從entry例項的value屬性裡獲取到最後所要的object物件

接下來討論一下上面出現的threadlocalmap類以及entry類,直接貼原始碼

static class threadlocalmap 

}... ...

/*** the table, resized as necessary.

* table.length must always be a power of two.

*/private entry table;

/*** the number of entries in the table.

*/private

int size = 0;

... ...

}

entry是threadlocalmap的內部類,而且threadlocalmap裡擁有乙個型別為entry的table屬性,而線每個執行緒例項有自己的threadlocalmap。到這裡結論已經很明顯了,

負責儲存threadlocal的key和value根本就不是乙個map型別,而是乙個entry陣列!

entry繼承weakreference,因此繼承擁有乙個弱引用referent,而且自身也有乙個value屬性。entry利用referent來儲存threadlocal例項的弱引用,利用value儲存object的強引用

最後的問題是怎樣在entry陣列裡定位我們需要的entry呢

還是看**說話

private entry getentry(threadlocal> key)
留意key.threadlocalhashcode這個屬性,entry在儲存進entry陣列之前,會利用threadlocal的引用計算出乙個hash值,然後利用這個hash值作為下標定位到entry陣列的某個位置;

相反,從entry取entry也是同樣道理。

最後來乙個圖來總結上面說的內容

客戶端訪問threadlocal例項的get方法,get方法通過thread.getcurrentthread獲得當前執行緒的例項,從而獲得當前執行緒的threadlocalmap物件,而threadlocalmap裡包含了乙個entry陣列,裡面的每個entry儲存了threadlocal引用以及object引用,entry的referent儲存threadlocal的弱引用,entry的value儲存object的強引用。

ThreadLocal是怎麼實現執行緒隔離的

案例 public static void main string args cc1 start new thread new runnable cc2 start 輸出 cc1 2 cc2 null threadlocal的set t t 方法原始碼 public void set t value...

敏捷是怎樣煉成的

很早之前,就有了寫 的衝動,寫一本給程式設計師看的 寫一本能夠反映中國程式設計師生活的 曾幾何時,沉默寡言 喜歡獨自思考 甚至 木吶 成為了程式設計師的標籤。其實在每個程式設計師心中,除了對技術的痴迷,他們也熱愛生活。他們改變著技術,也同時被技術改變著。他們是一群普通的人,也是自己心中的英雄。之所以...

高手是怎樣練成的

高手成長的六個階段 程式設計師怎樣才能達到程式設計的最高境界?最高境界絕對不是你去編兩行 或者是兒分鐘能寫幾行 或者是用什麼所謂的視覺化上具產生最少的 這些工作,這都不是真正的高手境界。即使足這樣的高手,那也都是無知者的自封。我認為,乙個程式設計師的成長可分為如下六個階段 第一階段 此階段主要是能熟...