我們知道,當多個執行緒訪問同一個變數時特別容易出現併發問題,特別是多個執行緒在對一個變數同時操作時。所以為了執行緒安全,一般是採用同步訪問該資源。在實際程式碼中,我們一般會用synchronized、ReentrantLock ,甚至是分散式鎖這些鎖來實現同步操作。
不過今天要介紹的是ThreadLocal,這個類線上程安全方面是怎麼實現的呢,帶著這個問題帶來今天的文章。
先來一段程式碼開始今天的分析, 如下:
這段程式碼,df是一個公共的變數,有兩個執行緒one和two都在訪問它,並通過set方法修改裡面的值,然後執行,結果永遠如下:
thread tow's value is : this is thread two
thread one's value is :this is thread one
至於打印出來的順序,這個其實是無所謂的,因為執行緒的執行你應該是了解的。
那接下來就分析下這個結果為什麼永遠會是這樣,而不是出現如下結果:
thread tow's value is : this is thread one
thread one's value is :this is thread two
接下來從原始碼層進行分析,set方法如下:
邏輯很好理解,先從may裡獲取,獲取到則進行設值
沒獲取到,建立map並進行設值。
首先開啟看下get這個方法,如下:
簡單吧,其實就是獲取了當前執行緒的一個內部屬性而已,這個屬性的型別是
ThreadLocalMap。
再看一下createMap的方法,如下:
也很簡單,其實就是把當前執行緒的屬性賦值操作而已。
ThreadLocalMap從命名上也可以大概看出是個特殊的Map,這裡不專門展開,後續有時間詳細分析一下這個類。
從程式碼上看出,在create的時候,僅僅是修改當前執行緒的屬性:threadLocals,既然成員屬性的話,那說明此塊記憶體屬於當前執行緒獨享(記憶體模式後面抽個專題詳細的講述,當前只需要知道執行緒獨享分配給自己的那塊記憶體即可),從而也就說明這個操作是執行緒安全的。
從而也就說明,在get的時候獲取到的值就是當前執行緒的成員變數。
從以上程式碼可以看出,ThreadLocal其實就是操作執行緒的一個殼子而已,對執行緒API較為熟悉的話,自己也是可以寫出來的,只是我們作為使用者,站在巨人的肩膀上看的更高而已。
對於初學者來說,不能僅知道為什麼是像別人的講的那樣,還是需要多看看原始碼自己加深一下印象,對自己是有好處的。