ThreadLocal是用來處理多線程併發問題的一種解決方案。ThreadLocal是的做用是提供線程的局部變量,在多線程併發環境下,提供了與其餘線程隔離的局部變量。一般這樣的設計的狀況是由於這個局部變量是不適合放在全局變量進行同步處理的。好比在事務管理中,在service類中的涉及到事務的方法,每一個事務的上下文都應該是獨立擁有數據庫的connection鏈接的,不然在數據提交回滾過程當中就會產生衝突。java
spring中使用ThreadLocal來設計TransactionSynchronizationManager類,實現了事務管理與數據訪問服務的解耦,同時也保證了多線程環境下connection的線程安全問題。spring
DataSourceTransactionManager的實現中,doBegin()方法開啓事務,咱們看下它是怎麼處理connection資源的。數據庫
首先從數據庫鏈接池中得到一個connection,並構造一個connection包裝類,使用這個包裝類開啓事務,最後經過TransactionSynchronizationManager將connection與ThreadLocal綁定,事務提交或者回滾後,解除綁定。安全
TransactionSynchronizationManager中bindResource()的實現多線程
Resource就是ThreadLocal,而這裏的Map就是ThreadLocalMap的value,與當前線程關聯的ThreadLocal的值。併發
ThreadLocal又是如何爲每一個線程維護一個獨立的局部變量的呢?this
首先在Thread類中,都會維護一個ThreadLocalMap映射表,這個映射表存儲的key是ThreadLocal自己,value則是咱們存儲的局部變量object。spa
ThreadLocal類中get方法和set方法的實現。線程
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); }
咱們再看getMap的實現設計
ThreadLocalMap getMap(Thread t) { return t.threadLocals; } void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue); }
從代碼實現中能夠看出,每一個線程Thread都會維護本身的ThreadLocalMap,這個map的key則是ThreadLocal類自己,而value則是咱們保存的數據。ThreadLocal在多線程中是被公共持有的,被隔離的數據實際是存放在每一個線程的ThreadLocalMap中的,只不過是經過ThreadLocal的引用獲得每一個線程維護的ThreadLocalMap中的value。