[英]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.