简体   繁体   English

ThreadLocal:为什么一个线程所做的更改在另一个线程中可见

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

Consider following code:考虑以下代码:

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: 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]

Why changes made by Thread2(ie removing of 1 and addition of 2) is visible to thread1 also?为什么 Thread2 所做的更改(即删除 1 和添加 2)对 thread1 也是可见的? What will be the ideal use case here?这里的理想用例是什么?

A thread local is not a copy of the value (what you are storing), it's more like a copy of the variable (the place you are storing it).线程本地不是值的副本(您存储的内容),它更像是变量的副本(您存储它的位置)。 It's a variable that stores (generally) a different value for each thread that accesses it.它是一个变量,它(通常)为访问它的每个线程存储不同的值。

While the ThreadLocal is capable of referencing different values in each thread, you have assigned the same value to both.虽然ThreadLocal能够在每个线程中引用不同的值,但您已经为两者分配了相同的值。 Mutations of the value in one thread happen to be visible in the other.一个线程中值的突变恰好在另一个线程中可见。 (This is not guaranteed, however; this concurrent access to a HashSet is likely to result in bugs.) (但是,这并不能保证;这种对HashSet的并发访问可能会导致错误。)

A more useful application of ThreadLocal would assign distinct values for each thread. ThreadLocal的一个更有用的应用程序将为每个线程分配不同的值。 In your example, this means creating a HashSet inside the Runnable .在您的示例中,这意味着在Runnable中创建一个HashSet This maintains the isolation of each value to one thread, and avoids the concurrency bugs you have in your code.这保持了每个值与一个线程的隔离,并避免了代码中的并发错误。

I am not sure there is an "ideal" use case for ThreadLocal ;我不确定ThreadLocal是否有“理想”用例; I see it as a tool for workarounds when the ideal is not possible.当无法实现理想时,我将其视为解决方法的工具。 I see them as a necessary evil, a last resort.我认为它们是必要的邪恶,最后的手段。 But, for example, you could use a ThreadLocal to pass extra data up and down the stack when it can't be passed as method parameters.但是,例如,当不能作为方法参数传递时,您可以使用ThreadLocal在堆栈上下传递额外数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM