執行緒區域性變數ThreadLocal實現原理

2022-06-26 07:57:12 字數 2936 閱讀 6872

之前做專案用到過threadlocal,但是沒有看原始碼層面的具體實現,今天特來補一補課。

threadlocal,即執行緒區域性變數,用來為每乙個使用它的執行緒維護乙個獨立的變數副本。

那種以時間換取空間的做法不同,threadlocal沒有任何鎖機制,它以空間換取時間的方式保證變數的執行緒安全

1、threadlocal類圖結構

threadlocalmap:是threadlocal的靜態內部類,也是實際儲存變數的類。

entry:是threadlocalmap的靜態內部類。threadlocalmap持有乙個entry陣列,以threadlocal為key,變數為value,封裝乙個entry。

2、thread,threadlocal,threadlocalmap和entry的關係

說明:乙個thread擁有乙個threadlocalmap物件;

乙個threadlocalmap擁有多個entry陣列;

每個entry都有k--v;

entry的key就是某個具體的threadlocal物件,是弱引用,key丟失後,gc不會**value會造成oom(後面詳細說)

3、threadlocal的set()方法

public

void

set(t value)

可看出:

1、乙個thread只擁有乙個threadlocalmap物件;

2、具體存值呼叫的是threadlocalmap的set(),傳入的引數key就是當前threadlocal物件。

3.1、threadlocalmap的set()方法

private

void set(threadlocal>key, object value)

if (k == null

) }

tab[i] = new entry(key, value);// 3

int sz = ++size;

if (!cleansomeslots(i, sz) && sz >= threshold)// 4

rehash();

}

可看出:

1、通過key的hashcode與陣列容量 -1 取模,計算陣列index;

2、從當前index開始遍歷,清除key為null的無效entry

3、將k-v封裝為entry,並放入陣列

4、判斷是否需要進行entry陣列擴容。threshold的值為陣列容量的2/3。

大家可以回顧一下hashmap的原始碼,是不是很相似?

index都是和長度-1取模,也都是容量不夠了,超出閾值就擴容(這裡是擴容為2倍,和hashmap一樣)。

3.2、擴容方法resize()

private

void

resize() else}}

setthreshold(newlen);

size =count;

table =newtab;

}

1、然後遍歷舊陣列,根據新陣列容量重新計算entry在新陣列中的位置。

4、threadlocal的get()方法

public

t get()

}return

setinitialvalue();

}

4.1、threadlocalmap的getentry()方法

private entry getentry(threadlocal>key) 

private entry getentryaftermiss(threadlocal> key, int

i, entry e)

return

null

; }

5、threadlocal的remove()方法

public

void

remove()

private

void remove(threadlocal>key) }}

注意:

static

class entry extends

weakreference

> {}

threadlocal可能存在oom問題。

因為threadlocalmap是使用threadlocal的弱引用作為key的,發生gc時,key被**,這樣我們就無法訪問key為null的value元素。

如果value本身是較大的物件,那麼執行緒一直不結束的話,value就一直無法得到**。特別是在我們使用執行緒池時,執行緒是復用的,不會殺死執行緒,這樣threadlocal弱引用被**時,value不會被**。

所以,在使用threadlocal時,執行緒邏輯**結束時,必須顯示呼叫threadlocal.remove()方法。

1、執行緒區域性變數threadlocal實現原理

over.......

DLL 執行緒區域性變數

1.用 declspec thread 建立執行緒區域性變數 declspec thread int tls count 0 注意事項 當用 declspec thread 宣告執行緒區域性變數的時候,應注意以下事項 1 只能用來宣告或者定義具有static作用域的變數,而不能用來宣告或者定義區域性...

多執行緒 執行緒內區域性變數

該類提供了執行緒內區域性 thread local 變數。好比有兩個視窗 兩個執行緒 乙個視窗可以拿飲料,乙個視窗可以拿食物。現在有多個人要來拿東西,如果在飲料視窗有的人拿到了飲料,有的人拿到了不該拿的食物,就說明執行緒之間出現了混亂,我們應當避免這種情況出現。以下 就可能會出現執行緒混亂的問題 p...

ThreadLocal執行緒區域性變數 多執行緒與高併發

threadlocal執行緒區域性變數,實現了將物件變數儲存在特定的執行緒物件中,僅對當前執行緒可見。我們在測試程式中,乙個執行緒往threadlocal物件中放置物件,然後另乙個物件來取物件取不到。public class testthreadlocal catch interruptedexce...