關(guān)鍵字: java 線程 threadlocal
昨天上Java版塊逛了一圈,一個(gè)2萬(wàn)5千人瀏覽的帖子引起了偶滴注意 ThreadLocal與synchronized ,9頁(yè)以上的回復(fù),足見大家對(duì)這個(gè)問(wèn)題的興趣。
老實(shí)說(shuō),從看到這個(gè)帖子的題目開始,就覺得帖子的作者估計(jì)是在概念上有所混淆了,于是乎想寫個(gè)咚咚,同大家分享一下自己的心得。
帖子上,討論的人很多,高手不乏,各抒己見,但不知新手們看明白沒有,因此,這里偶以最簡(jiǎn)潔列表方式來(lái)說(shuō)一說(shuō)相關(guān)問(wèn)題。
1.區(qū)別ThreadLocal 與 synchronized
- ThreadLocal是一個(gè)線程隔離(或者說(shuō)是線程安全)的變量存儲(chǔ)的管理實(shí)體(注意:不是存儲(chǔ)用的),它以Java類方式表現(xiàn);
- synchronized是Java的一個(gè)保留字,只是一個(gè)代碼標(biāo)識(shí)符,它依靠JVM的鎖機(jī)制來(lái)實(shí)現(xiàn)臨界區(qū)的函數(shù)、變量在CPU運(yùn)行訪問(wèn)中的原子性。
2.理解ThreadLocal中提到的變量副本
事實(shí)上,我們向ThreadLocal中set的變量不是由ThreadLocal來(lái)存儲(chǔ)的,而是Thread線程對(duì)象自身保存。當(dāng)用戶調(diào)用ThreadLocal對(duì)象的set(Object o)時(shí),該方法則通過(guò)Thread.currentThread()獲取當(dāng)前線程,將變量存入Thread中的一個(gè)Map內(nèi),而Map的Key就是當(dāng)前的ThreadLocal實(shí)例。請(qǐng)看源碼,這是最主要的兩個(gè)函數(shù),能看出ThreadLocal與Thread的調(diào)用關(guān)系:
1
public void set(T value) {
2
Thread t = Thread.currentThread();
3
ThreadLocalMap map = getMap(t);
4
if (map != null)
5
map.set(this, value);
6
else
7
createMap(t, value);
8
}
9
10
ThreadLocalMap getMap(Thread t) {
11
return t.threadLocals;
12
}

2

3

4

5

6

7

8

9

10

11

12

(有興趣的朋友可以閱讀Java的ThreadLocal源碼)因此,我們可以知道,所謂的變量副本,即是對(duì)Object Reference(對(duì)象引用)的拷貝。
3.理解Thread和 ThreadLocal對(duì)變量的引用關(guān)系
實(shí)際上Thread和ThreadLocal對(duì)變量引用關(guān)系就像是坐標(biāo)系中的X軸和Y軸,是從兩個(gè)維度上來(lái)組織對(duì)變量的引用的。
- 首先說(shuō)Thread。 我們知道一個(gè)ThreadOne的執(zhí)行會(huì)貫穿多個(gè)方法MethodA、MethodB、MethodC這些方法可能分布于不同的類實(shí)例。假設(shè),這些方法分別使用了ThreadLocalA、ThreadLocalB、ThreadLocalC來(lái)保存線程本地變量,那么這些變量都存于ThreadOne的Map中,并使用各自的ThreadLocal實(shí)例作為key。 因此,可以認(rèn)為,借助ThreanLocal的set方法,在X軸上,Thread橫向關(guān)聯(lián)同一線程上下文中來(lái)自多個(gè)Method的變量引用副本。

- 接著說(shuō)ThreadLocal。 一個(gè)MethodA中的X變量將被多個(gè)線程ThreadOne、ThreadTwo、ThreadThree所訪問(wèn)。假設(shè)MethodA使用ThreadLocal存儲(chǔ)X,通過(guò)set方法,以ThreadLocal作為key值,將不同線程來(lái)訪時(shí)的不同的變量值引用保存于ThreadOne、ThreadTwo、ThreadThree的各自線程上下文中,確保每個(gè)線程有自己的一個(gè)變量值。因此,可以認(rèn)為,ThreadLocal是以Method為Y軸,縱向關(guān)聯(lián)了處于同一方法中的不同線程上的變量。

希望能對(duì)大家有所幫助,這樣可以少走很多彎路哦。