Java多线程之ThreadLocal原理详解

介绍:

ThreadLocal是一种避免多线程访问出现线程不安全的方法,当我们创建一个变量后,如果每个线程对其访问的时候都是线程自己的变量,这样就可以避免线程不安全问题,这就是ThreadLocal所做的。
ThreadLocal他提供线程本地变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。如果创建一个ThrealLocal变量,那么访问这个变量的每个线程都会有一个这个变量的副本。在实际多线程操作的时候,操作的是自己本地内存的变量。
我们再来看一下ThreadLocal<>类中的方法就更加清晰了,具体含义往下看。
在这里插入图片描述

原理:

在学习ThreadLoacl原理之前,我们应该搞明白Thread、ThreadLocal、ThreadLocalMap这三个概念和他们之间的联系。

Thread有ThreadLocal.ThreadLocalMap类型的属性threadLocals。源码如下:

/* ThreadLocal values pertaining to this thread. This map is maintained
 * by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;

ThreadLocalMap是ThreadLocal的一个内部类,ThreadLocalMap中用于存储数据的entry定义代码:
从中我们可以看到这个Map的key是ThreadLocal的一个实例对象,value则是具体的值

static class ThreadLocalMap {
    static class Entry extends WeakReference<ThreadLocal<?>> {
        /** The value associated with this ThreadLocal. */
        Object value;
        Entry(ThreadLocal<?> k, Object v) {
            super(k);
            value = v;
        }
    }

由ThreadLocal对Thread的ThreadLocalMap赋值

/**
 * Create the map associated with a ThreadLocal. Overridden in
 * InheritableThreadLocal.
 *
 * @param t the current thread
 * @param firstValue value for the initial entry of the map
 */
void createMap(Thread t, T firstValue) {
    t.threadLocals = new ThreadLocalMap(this, firstValue);
}

我们再来看一下ThreadLocal里面的方法具体含义:
ThreadLocal类核心方法set、get、initialValue、withInitial、setInitialValue、remove:
(1)set方法源码解释:

public void set(T value) {  //设置当前线程对应的局部变量值
    //获取当前的线程
    Thread t = Thread.currentThread();
    //先取出当前线程对应的threadLocalMap这个属性值
    ThreadLocalMap map = getMap(t);
    //如果它不是空,则将value放入以this,即以threadLocal对象为key的映射的map中
    if (map != null)
        map.set(this, value);
    else
    //否则则创建一个
        createMap(t, value);
}
上述方法调用了getMap()方法
ThreadLocalMap getMap(Thread t) {
    return t.threadLocals;//返回线程自己的变量ThreadLocalMap类型的threadLocals
    并绑定到当前线程的成员变量ThreadLocal上
}

(2)get方法:get该方法返回当前线程所对应的线程局部变量。和set类似,也是先取出当前线程对应的threadLocalMap,如果不存在则创建一个,但是是用inittialValue作为value放入到map中,且返回initialValue,否则就直接从map取出this即threadLocal对应的value返回。

public T get() { 
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    //如果ThreadLocal不为空,就在map中查找本地变量值
    if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            @SuppressWarnings("unchecked")
            T result = (T)e.value;
            return result;
        }
    }
    //threadLocals为空,就调用更改初始化当前线程的threadLocals变量
    return setInitialValue();
}

参考博客:https://blog.youkuaiyun.com/lufeng20/article/details/24314381
https://zhuanlan.zhihu.com/p/61587053

https://www.cnblogs.com/fsmly/p/11020641.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值