ThreadLocal 原始碼分析

2022-02-06 18:53:28 字數 2594 閱讀 6209

一、定義

threadlocal會為每乙個執行緒提供乙個獨立的變數副本,從而隔離了多個執行緒對資料的訪問衝突。因為每乙個執行緒都擁有自己的變數副本,從而也就沒有必要對該變數進行同步了。threadlocal提供了執行緒安全的共享物件,在編寫多執行緒**時,可以把不安全的變數封裝進threadlocal。

概括起來說,對於多執行緒資源共享的問題,同步機制採用了「以時間換空間」的方式,而threadlocal採用了「以空間換時間」的方式。前者僅提供乙份變數,讓不同的執行緒排隊訪問,而後者為每乙個執行緒都提供了乙份變數,因此可以同時訪問而互不影響。

但是要注意,雖然threadlocal能夠解決上面說的問題,但是由於在每個執行緒中都建立了副本,所以要考慮它對資源的消耗,比如記憶體的占用會比不使用threadlocal要大。

二、基本使用

示例

public static void main(string args)  else 

}system.out.println(thread.currentthread().getname() + " " + threadlocal.get());

}).start();

}system.out.println(thread.currentthread().getname() + " " + threadlocal.get());

}

輸出結果:

main 999

thread-0 2000

thread-1 2000

thread-2 2000

上述示例說明:執行緒與執行緒之間相互隔離,且執行緒安全。threadlocal作用域為當前執行緒

三、原始碼分析

threadlocal為什麼可以做到每乙個執行緒都有乙份變數的副本,其實原理很簡單

threadlocal原理同hashmap原理是一樣的,核心為threadlocalmap,只不過是map的key為當前執行緒,通過thread.currentthread()獲取。只要是在同乙個執行緒內,只要你執行set方法,這個key永遠保持不變,即每乙個執行緒對應乙個value。

我們先通過threadlocal的set方法來分析

// set方法一般都是set(key, value),因為threadlocalmap使用了當前執行緒作為key,所以省略了,get()方法也一樣。

public void set(t value)

threadlocalmap getmap(thread t)

void createmap(thread t, t firstvalue)

首次在呼叫 set方法時,會執行createmap,在createmap方法中又會建立乙個threadlocalmap物件,我們再來看一下threadlocalmap這個構造方法

構造方法

threadlocalmap(threadlocal<?> firstkey, object firstvalue)

通過構造方法,我們可以看出threadlocal底層使用的就是hashmap結構

threadlocalmap繼承了weakreference

static class threadlocalmap         

}private static final int initial_capacity = 16;

private entry table;

}

threadlocal為什麼要使用弱引用?

首先我們看乙個weakhashmap的示例,weakhashmap也是它的 entry類繼承了weakreference

public static void main(string args) throws interruptedexception 

key = null;

key2 = null; // 不會被**

system.gc();

system.out.println(weakmap); //

}

我們可以看出weakhashmap針對key作了**,而在整個map中並沒有真正的**此物件。在threadlocal中,它使用當前執行緒作為key的,如果執行緒生命週期結束後,即這個key以及對就的value都應該被gc掉

記憶體洩露問題

雖然上述的弱引用解決了key,也就是執行緒的threadlocal能及時被**,但是value卻依然存在記憶體洩漏的問題。當把threadlocal例項置為null以後,沒有任何強引用指向threadlocal例項,所以threadlocal將會被gc**。map裡面的value卻沒有被**.而這塊value永遠不會被訪問到了。所以存在著記憶體洩露,因為存在一條從current thread連線過來的強引用。只有當前thread結束以後, current thread就不會存在棧中,強引用斷開, current thread, map, value將全部被gc**.

threadlocal和synchonized的比較:

當然threadlocal並不能替代synchronized,它們處理不同的問題域。synchronized用於實現同步機制,比threadlocal更加複雜。

ThreadLocal實現原理與原始碼分析

threadlocal底層實現內部類 threadlocalmap 一 threadlocal的set方法原始碼分析 1 public void set t value thread t thread.currentthread threadlocalmap map getmap t if map ...

ThreadLocal原始碼理解

threadlocal其實原理是建立了多份相同資料儲存在堆記憶體上,每個執行緒的thread類裡有threadlocal.threadlocalmap threadlocals的屬性來指向存位置,所以每個執行緒修改都不會影響到其他執行緒的資料 首先說下下面用到的東西 threadlocalmap為t...

ThreadLocal原始碼分析

在理解handler looper之前,先來說說threadlocal這個類,聽名字好像是乙個本地執行緒的意思,實際上它並不是乙個thread,而是提供乙個與執行緒有關的區域性變數功能,每個執行緒之間的資料互不影響。我們知道使用handler的時候,每個執行緒都需要有乙個looper物件,那麼and...