为什么ThreaLocal是线程独享的

什么是ThreadLocal:

多线程访问同一个共享变量的时候容易出现并发问题,特别是多个线程对一个变量进行写入的时候,为了保证线程安全,一般使用者在访问共享变量的时候需要进行额外的同步措施才能保证线程安全性。ThreadLocal是除了加锁这种同步方式之外的一种保证一种规避多线程访问出现线程不安全的方法,当我们在创建一个变量后,如果每个线程对其进行访问的时候访问的都是线程自己的变量这样就不会存在线程不安全问题。
  ThreadLocal是JDK包提供的,它提供线程本地变量,如果创建一乐ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的一个副本,在实际多线程操作的时候,操作的是自己本地内存中的变量,从而规避了线程安全问题。

为什么ThreadLocal可以避免线程安全问题:

    我们来先看一下ThreadLocal的get和set方法
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);
    }

我们在调用get和set方法时都会运行两行代码,
Thread t = Thread.currentThread(); //获取当前线程
ThreadLocalMap map = getMap(t);//获取ThreadLocalMap对象,注意这个getMap方法,这个是避免线程安全问题的关键

    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }
ThreadLocal.ThreadLocalMap threadLocals = null;

在每个线程中会有一个ThreadLocalMap,ThreadLocal在get和set时实际上是往线程中的ThreadLocalMap中存取对象,所以其他线程是获取不到当前线程的值的,但是有一种特殊情况需要注意,那就是线程池
因为线程池中的核心线程是不会被销毁的,所有有可能会出现下一个请求获取到前一个请求的值的情况
因此需要注意在每次用完ThreadLocal后要将其中的数据remove掉。如果不做remove操作的话还有可能会引起内存泄漏问题

如果我们想让子线程共享父线程中的ThreadLocal应该怎么办?

使用InheritableThreadLocal即可。

为什么InheritableThreadLocal可以解决这个问题

我们来看一下Thread中的init方法就明白了。
其中有几行代码是这样的:

if (inheritThreadLocals && parent.inheritableThreadLocals != null){
	this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
}   

从这三行代码我们可以发现,子线程创建是会判断父线程中的inheritableThreadLocals 是否有值,如果有就将其中的值复制一份到自己的inheritableThreadLocals 对象中,注意,这里是复制一份,因为在createInheritedMap方法中会重新创建一个ThreadLocalMap对象。因此子线程中修改不会影响创建之后不会相互影响。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值