ThreadLocal原理分析

ThreadLocal 爲了解決多線程併發提供了一種新的思路,ThreadLocal 爲每一個變量維護一個線程的副本,每一個線程能夠獨立的修改副本,不會影響到其餘線程。使用 ThreadLocal 可能須要注意引用的釋放,若是忘記釋放可能會致使對象釋放不了。

ThreadLocal 寫數據過程:java

  1. 從 ThreadLocal 的 set 方法中咱們能夠看到, ThreadLocal 首先獲取到了當前線程, 並獲取到 Thread 的 threadLocals 變量;
  2. 拿到 threadLocals 後,經過這個 ThreadLocalMap 使用 ThreadLocal 對象做爲鍵,拿到相應的數據,由於 threadLocals 是屬於當前線程的,只有當前線程才能拿到該對象,因此沒有併發問題。


ThreadLocal 讀數據過程:多線程

  1. 從 ThreadLocal 的 get 方法中咱們能夠看到, ThreadLocal 首先獲取到了當前線程, 並獲取到 Thread 的 threadLocals 變量;
  2. 拿到 threadLocals 後,若是 threadLocals 爲空,則使用數據建立一個 ThreadLocalMap 對象,並賦值給當前線程的 threadLocals 變量;若是不爲空,則直接使用 threadLocals 設置數據,由於 threadLocals 是屬於當前線程的,只有當前線程才能拿到該對象,因此寫一樣併發問題。

      總的來講,ThreadLocal 將數據存儲在當前線程的 Thread.threadLocals 這個 ThreadLocalMap 中,並且只有當前線程才能得到這個變量,因此 ThreadLocal 不存在併發問題。

ThreadLocal 結構:併發

public class ThreadLocal<T> {
    private final int threadLocalHashCode = nextHashCode();
    private static AtomicInteger nextHashCode = new AtomicInteger();
    private static final int HASH_INCREMENT = 1640531527;

    public T get() {
        // 獲取當前線程,並拿到 threadLocals
        Thread var1 = Thread.currentThread();
        ThreadLocal.ThreadLocalMap var2 = this.getMap(var1);
        if(var2 != null) {
            // 經過 this 拿到存在當前線程 threadLocals 中的對象
            ThreadLocal.ThreadLocalMap.Entry var3 = var2.getEntry(this);
            if(var3 != null) {
                Object var4 = var3.value;
                return var4;
            }
        }

        return this.setInitialValue();
    }

    private T setInitialValue() {
        Object var1 = this.initialValue();
        Thread var2 = Thread.currentThread();
        ThreadLocal.ThreadLocalMap var3 = this.getMap(var2);
        if(var3 != null) {
            var3.set(this, var1);
        } else {
            this.createMap(var2, var1);
        }

        return var1;
    }

    public void set(T var1) {
        // 獲取當前線程,並拿到 threadLocals
        Thread var2 = Thread.currentThread();
        ThreadLocal.ThreadLocalMap var3 = this.getMap(var2);
        if(var3 != null) {
            // 若是 map 不爲空,經過 this 將對象存到當前線程 threadLocals 中
            var3.set(this, var1);
        } else {
            // 若是 map 爲空,則建立新的 map,並將對象存到 threadLocals 中
            this.createMap(var2, var1);
        }

    }

    public void remove() {
        ThreadLocal.ThreadLocalMap var1 = this.getMap(Thread.currentThread());
        if(var1 != null) {
            var1.remove(this);
        }
    }

    // 獲取線程的 threadLocals 變量
    ThreadLocal.ThreadLocalMap getMap(Thread var1) {
        return var1.threadLocals;
    }

    void createMap(Thread var1, T var2) {
        var1.threadLocals = new ThreadLocal.ThreadLocalMap(this, var2);
    }
}
相關文章
相關標籤/搜索