簡體   English   中英

ThreadLocal:為什么一個線程所做的更改在另一個線程中可見

[英]ThreadLocal: why changes made by one thread is visible in other thread

考慮以下代碼:

public static void main(String args[]) {
        
        
        Set<Integer> set=new HashSet<>();
       set.add(1);
        
        ThreadLocal<Set> var1=new ThreadLocal<>();
        
        //THREAD1
        Runnable r=()->{
                    
            var1.set(set);

            for(int i=1;i<=10;i++)
             System.out.println("Thread ID:"+Thread.currentThread()+":  "+var1.get());
            };

        Thread th=new Thread(r);
        th.start();
        
        //THREAD2
        Thread th1=new Thread(()-> {
                
            var1.set(set);
            
            var1.get().remove(1); //removing 1 from this thread copy of set.
            var1.get().add(2);    //adding 2 to this thread copy of set 
            
            for(int i=1;i<=10;i++)
             System.out.println("Thread ID:"+Thread.currentThread()+":  "+var1.get());
             
        });
        th1.start();
        
        
    }

Output:

Thread ID:Thread[Thread-0,5,main]:  [2]
Thread ID:Thread[Thread-0,5,main]:  [2]
Thread ID:Thread[Thread-0,5,main]:  [2]
Thread ID:Thread[Thread-0,5,main]:  [2]
Thread ID:Thread[Thread-0,5,main]:  [2]
Thread ID:Thread[Thread-0,5,main]:  [2]
Thread ID:Thread[Thread-0,5,main]:  [2]
Thread ID:Thread[Thread-0,5,main]:  [2]
Thread ID:Thread[Thread-0,5,main]:  [2]
Thread ID:Thread[Thread-0,5,main]:  [2]
Thread ID:Thread[Thread-1,5,main]:  [2]
Thread ID:Thread[Thread-1,5,main]:  [2]
Thread ID:Thread[Thread-1,5,main]:  [2]
Thread ID:Thread[Thread-1,5,main]:  [2]
Thread ID:Thread[Thread-1,5,main]:  [2]
Thread ID:Thread[Thread-1,5,main]:  [2]
Thread ID:Thread[Thread-1,5,main]:  [2]
Thread ID:Thread[Thread-1,5,main]:  [2]
Thread ID:Thread[Thread-1,5,main]:  [2]
Thread ID:Thread[Thread-1,5,main]:  [2]

為什么 Thread2 所做的更改(即刪除 1 和添加 2)對 thread1 也是可見的? 這里的理想用例是什么?

線程本地不是值的副本(您存儲的內容),它更像是變量的副本(您存儲它的位置)。 它是一個變量,它(通常)為訪問它的每個線程存儲不同的值。

雖然ThreadLocal能夠在每個線程中引用不同的值,但您已經為兩者分配了相同的值。 一個線程中值的突變恰好在另一個線程中可見。 (但是,這並不能保證;這種對HashSet的並發訪問可能會導致錯誤。)

ThreadLocal的一個更有用的應用程序將為每個線程分配不同的值。 在您的示例中,這意味着在Runnable中創建一個HashSet 這保持了每個值與一個線程的隔離,並避免了代碼中的並發錯誤。

我不確定ThreadLocal是否有“理想”用例; 當無法實現理想時,我將其視為解決方法的工具。 我認為它們是必要的邪惡,最后的手段。 但是,例如,當不能作為方法參數傳遞時,您可以使用ThreadLocal在堆棧上下傳遞額外數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM