再挖一挖ThreadLocal
阿新 • • 發佈:2020-07-24
關於ThreadLocal原始碼分析的文章可以說多如牛毛,不僅是由於ThreadLocal原始碼簡潔,還因為它是由Java界的兩個大師級的作者編寫,Josh Bloch和Doug Lea。Josh Bloch 在 Sun 公司多年為 Java 平臺作出了傑出貢獻,包括JDK5語言增強、Java集合(Collections)框架,現在 Google 就職,是獲獎圖書《Effective Java》及《Effective Java: Second Edition》的作者。Doug Lea是JUC包的作者,Java併發程式設計的泰斗。筆者寫這篇部落格起初是因為一直對ThreadLocal中的魔數0x61c88647有疑惑,為使這塊內容較完整,也就按照通常的內容結構來寫了,然而在寫的過程中再次感受到,即使再熟悉的東西,仔細思考總結,依然收穫滿滿,推薦小夥伴們也動筆寫起來~
目錄
一. ThreadLocal做什麼的
ThreadLocal類可以看作為執行緒提供區域性變數的工具類,也就是說如果定義了一個ThreadLocal,每個執行緒往這個ThreadLocal中讀寫是執行緒隔離的,互相之間不會影響,是執行緒安全的。與區域性變數對應的就是共享變量了,如果多個執行緒共享一個變數,併發環境下讀寫共享變數是執行緒不安全的,為處理這種併發問題,常用做法就是加鎖。加鎖還是使用區域性變數就需要我們根據實際情況去權衡了。
我們先看下ThreadLocal的用法,以下是原始碼中提供的例子:為每個執行緒生成唯一id,執行緒第一次訪問ThreadLocal會觸發initialValue()方法,因此執行緒呼叫ThreadId.get()時得到唯一id:
import java.util.concurrent.atomic.AtomicInteger; public class ThreadId { // Atomic integer containing the next thread ID to be assigned private static final AtomicInteger nextId = new AtomicInteger(0); // Thread local variable containing each thread's ID private static final ThreadLocal<Integer> threadId = new ThreadLocal<Integer>() { @Override protected Integer initialValue() { return nextId.getAndIncrement(); } }; // Returns the current thread's unique ID, assigning it if necessary public static int get() { return threadId.get(); } }