刨根問底-ThreadLocal線程安全


一、線程安全,值得是在多線程環境先,一個類在執行某個方法時,對類的內部實例變量的訪問時安全的。所以,對於下面列出來的2類變量,不存在任何線程安全的說法: java

(1)方法簽名中的任何參數變量 安全

(2)處於方法內部的局部變量 多線程

線程安全針對於類內部的全局變量 併發

二、java.lang.ThreadLocal類是jdk提供一種解決多線程併發問題方案。 this

ThreadLocal類在維護變量時,實際使用了當前線程Thread中的一個叫作ThreadLocalMap的獨立副本,每一個線程能夠獨立修改屬於本身的副本而不會相互影響,從而隔離了線程和線程,避免了線程訪問實例變量發生衝突的問題。 spa

TreadLocal自己並非一個線程,而是經過操做當前線程中的一個內部變量來達到與其餘線程隔離的目的。之因此叫TdreadLocal,表示了其操做的對象時線程的一個本地變量。 線程

如今看Thread代碼: code

public
class Thread implements Runnable {
ThreadLocal.ThreadLocalMap threadLocals = null;
}
ThreadLocalMap跟隨者當前的線程而存在。不用的線程Thread,擁有不一樣的ThreadLocalMap的本地實例變量,這就是副本的含義。

ThreadLocal是如何操做ThreadLocalMAP的 對象

public class ThreadLocal<T> {
public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null)
                return (T)e.value;
        }
        return setInitialValue();
    }
 public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }
}
 ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }
 void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }
ThreadLocalMap變量屬於線程的內部屬性,不一樣的線程擁有徹底不一樣的ThreadLocalMap變量

線程中的ThreadLocalMap變量的值是在ThreadLocal對象進行set和get操做時建立的,在建立以前首先檢查當前的線程中的ThreadLocalMap變量是否已經存在,若是不存在建立 get

使用當前線程的ThreadLocalMap的關鍵在於使用當前的ThreadLocal的實例做爲key進行存儲。同一個線程中,不一樣的ThreadLocal實例操做的對象之間相互隔離。

上面內容參考《struts2技術內幕》

相關文章
相關標籤/搜索