圖解ThreadLocal原理

在項目中不少地方會用到ThreadLocal對象,用來實現線程之間資源隔離。現在通過圖的方式接解刨其原理。

public static void main(String[] arg) throws InterruptedException, IOException {
        final ThreadLocal t = new ThreadLocal();
        Thread thread_1 = new Thread(new Runnable(){
            @Override
            public void run() {
                t.set("thread_1");
                try {
                    Thread.sleep(50);
                    System.out.println("thread_1");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(t.get());
            }
        });
        Thread thread_2 = new Thread(new Runnable(){
            @Override
            public void run() {
                t.set("thread_2");
                try {
                    Thread.sleep(50);
                    System.out.println("thread_2");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(t.get());
            }
        });
        Thread thread_3 = new Thread(new Runnable(){
            @Override
            public void run() {
                t.set("thread_3");
                try {
                    Thread.sleep(50);

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(t.get());
            }
        });
        thread_1.start();
        thread_2.start();
        thread_3.start();
        System.in.read();
        Thread.currentThread().join();

整個過程的關鍵就是:
1、每個線程都有自己的ThreadLocalMap對象;(ThreadLocal 多線程下資源隔離的根本原因)

2、各個線程在調用同一個ThreadLocal對象的set(value)設置值的時候,是往各自的ThreadLocalMap對象數組中設置值

3、至於當前值放置在數組中的下標位置,則是通過ThreadLocal對象的threadLocalHashCode計算而來。即多線程環境下ThreadLocal對象的threadLocalHashCode是共享的。

4、而ThreadLocal對象的threadLocalHashCode是一個原子自增的變量,通過類方法初始化值。
也即,ThreadLocal a = new ThreadLocal();就會初始化threadLocalHashCode值,這個值不會再變。所以,同一個線程在同一個ThreadLocal對象中set()值,只能保存最後一次set的值。

5、爲什麼每個線程都有自己的ThreadLocalMap對象,且是一個數組呢?
答:根據以上的分析,多個線程操作一個ThreadLocal對象就能達到線程之間資源隔離。而採用數組是因爲可能一個線程需要通過多個ThreadLocal對象達到多個資源隔離。每個不同的ThreadLocal對象的threadLocalHashCode都不一樣,也就映射到ThreadLocalMap對象數組下的不同下標。

6、每個線程的ThreadLocalMap對象是通過偏移位置的方式解決hash碰撞

7、每個線程都有自己的ThreadLocalMap對象也有擴容機制,且是天然線程安全的
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章