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