當前位置:
首頁 > 最新 > ThreadLocal源碼分析

ThreadLocal源碼分析

線程安全性

我們在使用多線程技術開發時,線程的安全想是一個必須考慮的問題。當多個線程訪問某個類時,這個類始終都能表現出正確的行為,那麼就稱這個類是線程安全的。實現線程安全主要有三種方式。

線程封閉

將被訪問的數據限制在單個線程內,這種技術被稱為線程封閉。主要的實現有Ad-hoc線程封閉、棧封閉、ThreadLocal類

阻塞同步

使用Java內置鎖(synchronized)或顯示鎖(Lock)對共享資源進行訪問限制。當多個線程同一時刻訪問相同的資源時,必須要先持有鎖,只有當成功獲取鎖的線程可以訪問資源,其他的線程則會阻塞等待,直到鎖被釋放後開始新一輪的競爭鎖。

非阻塞同步

針對多處理器操作而設計的處理器中提供了一些特殊指令,用於管理對共享數據的並發訪問,JVM使用這些指令來實現鎖和並發的數據結構。典型的實現方式就是CAS操作。

在這三種方式中,線程封閉是實現線程安全性的最簡單方式。他的最佳實現則是ThreadLocal類。這個類能使線程中的某個值與保存值的對象關聯起來。ThreadLocal提供了get與set等訪問介面或方法,這些方法為每個使用該變數的線程都有一份獨立的副本,因此get總是返回有當前執行線程在調用set時設置的最新值。

ThreadLocal是如何做到這些呢,我們對他的源碼進行分析來一探究竟。

ThreadLocal源碼分析

首先了解一下ThreadLocal的整體架構圖:

每個Thread都包含了一個ThreadLocalMap對象,他是一個Map數據結構的類,key為ThreadLocal對象,value則是通過調用ThreadLocal#set保存的值。

ThreadLocal屬性:

有三個屬性值,每初始化一個新的Thread時,threadLocalHash+0x61c88647得到新的哈希值。

ThreadLocal#set方法:

當前線程的ThreadLocalMap為空時先初始化在賦值,否則直接複製。

ThreadLocalMap#set方法:

數據實際上都是保存在ThreadLocalMap的table數組中,首先通過key.threadLocalHashCode & (len-1)這一句是計算數據存儲在table數組中的位置;對數組的容量進行取余運算;數組的容量一定要是2^ n,這樣用(hashcode)&(2^n-1) 來計算正好就是取余運算,使數據在table中分布更均勻。

不同的ThreadLocal可能會得出計算出相同的table下標,當出現重複時一個地址怎麼存放多個數據呢?

ThreadLocalMap採用開發地址法解決。

用開放定址法解決衝突的做法是:當衝突發生時,使用某種探測技術在散列表中形成一個探測序列。沿此序列逐個單元地查找,直到找到給定的關鍵字,或者碰到一個開放的地址(即該地址單元為空)為止(若要插入,在探查到開放的地址,則可將待插入的新結點存人該地址單元)。查找時探測到開放的地址則表明表中無待查的關鍵字,即查找失敗。

在table中找到空位後,保存數據tab[i] = new Entry(key, value)。

保存完成後會清除table中的無效數據,當沒有從table中清除任何數據並且table中的實際長度是否超過總長度的3/2,這時會對table翻倍擴容。

ThreadLocal#get方法:

嘗試去獲得當前線程中的map,如果map不為空就從map中找到對應的值並且返回;

如果沒有存放ThreadLocal對象,則調用setInitialValue();

三、ThreadLocal應用場景

ThreadLocal對象通常用於防止對可變的單例變數或全局變數進行共享。例如,在單線程應用程序中可能會維持一個全局的資料庫連接,並在程序啟動時初始化這個鏈接對象,從而避免在調用每個方法時都要傳遞一個Connection對象。由於JDBC的鏈接對象不一定是線程安全的,因此,當多線程應用程序在沒有協同的情況下使用全局變數時,就不是線程安全的。通過將JDBC的鏈接保存到ThreadLocal對象中,每個線程都會擁有屬於自己的鏈接。

在實現應用程序框架時大量使用了ThreadLocal。例如,一個電商網站中,需要將一用戶的上下文信息與某個執行中的線程關聯起來。通過將用戶的上下文保存在靜態的ThreadLocal,很容易實現當需要獲取當前用戶的ID或判斷是有已授權時,只需要從ThreadLocal中直接讀取即可。

另外ThreadLocal變數類似於全局變數,他會降低代碼的可重用性並在類之間引入隱含的耦合性,因此在使用時要格外小心。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Java開發架構 的精彩文章:

TAG:Java開發架構 |