ThreadLocal为什么是线程安全的

如何看一个类是否是线程安全的?

     由JMM(Java内存模型)我们可以看出,在堆中的变量,如果同时被多个线程操作,就有可能出现线程安全问题(堆中的数据是线程共享的)。

     类分为有状态(有成员变量等)和无状态的, 无状态的类肯定是线程安全的, 我们都知道servlet,还有Spring中的bean都是单例的(在上下文中拿到的对象都是同一个),那它们是怎么保证线程安全的呢? 首先一点是bean最好是无状态的,即Dao,Service这些类最好不要有成员变量, 那这种肯定是安全的, 如果有怎么办, Spring是使用ThreadLocal来保证线程安全的。

线程副本

     每个线程(Thread)内部都有一个ThreadLocal.ThreadLocalMap, 可以看出ThreadLocalMap是ThreadLocal的一个静态内部类, 我们看一下源码:

       

      从代码中可以看出, ThreadLocalMap 里有一个Entry数组, Entry里有k, v字段, 而k就是当前的ThreadLocal对应, v就是要保存的变量值。

      在ThreadLocal中, 使用set, get方法来设置和获取数据, 这两个做了什么呢, 看下源码:

 public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }

public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

     先从当前线程里拿到ThreadLocalMap, 然后在从map里获取Entry(当前ThreadLocal对应作为key), entry的value值就是要获取的变量值;

     看出这里应该就清楚了ThreadLocal是如何保证线程安全的:

            1. 每个线程都有一个ThreadLoclMap成员变量(线程副本);

            2. ThreadLocal作为ThreadLocalMap的'key'来获取最终变量的值;

     每个线程拿到的ThreadLocalMap 变量肯定是线程私有的,所以不会被其他线程拿到,这样也就保证了线程的安全。

转载于:https://my.oschina.net/u/1177710/blog/899171

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值