关于threadLocal的疑惑

最近在看ThreadLocal的底层实现,通过查看源码发现此类主要的核心是通过获取到当前运行线程的一个变量threadLocals来为每一个线程提供一个本地存储。本人在网上看到很多对ThreadLocal讲解的帖子,一直不是特别理解他们说的副本是什么意思,为什么不会被其他线程干扰,是一个对象的深拷贝吗?但是在ThreadLocal中的set方法中也只是一个this.value=value;所以如果把同一个对象放入不同的两个线程的ThreadLocal中,其中一个线程对该对象的字段进行修改,其实是会影响到另一线程中的对象的。本人测试的结果也是如此。

public class MyThreadLocalTest {
    public static void main(String[] args) throws InterruptedException {
        ThreadLocal threadLocal = new ThreadLocal();
        ThreadLocal threadLocal2 = new ThreadLocal();
        Student a = new Student();
        threadLocal2.set(a);
        a.setName("mainThread");
        new Thread((
                () -> {

                    threadLocal.set(a);
                    ((Student) (threadLocal.get())).setName("myThread");

                    System.out.println("myThread 学生:" + threadLocal.get());
                }

        )).start();
//这里睡十秒 不然的话有可能主线程先执行
        Thread.sleep(10000);
        System.out.println("mainThread学生:" + threadLocal2.get());

    }
}

图片说明

本人在网上看到很多帖子以hibernate的session举例,但是本人只能理解到这个threadLocal只能保证到每个线程获取到同一个session对象而已,并不能解决多个线程拿到同一session后如果closs掉以后其他线程的session不被影响,希望大牛给予指点

3个回答

首先,你的理解没有问题,每个线程只能拿到字节 set 的这个值,因为它是全局维护了一个大 Map,key 是当前线程对象,指是它放入的对象。
其次,你开头说的这种用法其实是需要避免的,因为传入的是同一个对象,还是多线程之间共享了相同实例子,当然会相互干扰。
这个类型的用法一般都是创建各自线程自己运行过程中单独创建的对象的,不适合你开头说的相同实例共享的。

如果多线程共享相同对象,必须保证对象的各个操作都是有同步处理的,即这个类是线程安全的。要了解多线程的知识,推荐一本特别好的书:
《Java 并发编程实践》,JDK 的并发包的大牛们写的。

Lyrics1st
我的城市沒有海 好的 谢谢
8 个月之前 回复

不知道你最后一段话再说什么
threadLocal引用相同改变一个其他的自然会改变 应用内存是共享的(堆就那样 跟线程无关) threadLocal也只是一种数据结构

用法就错了,ThreadLocal存入的对象就不该是同一个。这玩意不保证线程安全。
所谓的副本是指,A线程存入的值,对B线程并不感知,B只能拿到自己存的值,并不能拿到A存入的值。
因为一般情况下ThreadLocal 都是定义为static类型的,如果没有ThreadLocal,那么B线程就可以获取A线程所存入的值。
理解了使用场景,很多地方就能想通了

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问