ThreadLocal部分源码解析

ThreadLocal提供了线程局部变量的实现,每个线程拥有自己独立的副本,避免线程间的数据干扰。ThreadLocal内部使用ThreadLocalMap,存储在Thread类中,每个Thread对象持有一个ThreadLocalMap。ThreadLocalMap基于Entry数组实现,Entry使用弱引用指向ThreadLocal对象,保证线程安全。ThreadLocal.get()方法通过当前线程找到ThreadLocalMap,以自身为索引获取value。了解ThreadLocal的工作原理有助于更好地利用它进行线程隔离。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 线程局部变量提供类,ThreadLocal< T >,简单说,对于某个变量(对象),为每个线程维护一个自己的独立副本,实现线程隔离

  2. ThreadLocal定义了内部静态类ThreadLocalMap,而Thread类内维护了一个ThreadLocalMap类型的成员变量:threadLocals

    /* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;
    
  3. 内部类复习:实例化非静态内部类,必须先实例化外部类,非静态内部类可访问外部类的成员;而静态内部类,不可访问内部类资源,且可以直接实例化。简单来讲,静态内部类仅仅是处于外部类内而已。另:静态内部类可以有多个实例(个人理解,静态内部类的定义代码类似于静态方法,确实只有一份,但它的实例是不受静态约束的)。

  4. 那么,可以得出如下结论:每个Thread类对象持有一个独立的ThreadLocalMap对象,而ThreadLocal类,仅仅是一个操作ThreadLocalMap的工具类,每一个ThreadLocal对象,都对应操作某种线程局部变量对象

  5. 对于ThreadLocal变量推荐用static修饰。(个人猜想原因是:一个ThreadLocal实例已经能对多线程内的ThreadLocalMap进行某种局部变量的“多操”,即 一个对一种

  6. ThreadLocalMap类似于一个简单的HashMap,不过是用Entry数组实现的。 Entry 是其静态内部类:

    /**
     * The entries in this hash map extend WeakReference, using
     * its main ref field as the key (which is always a
     * ThreadLocal object).  Note that null keys (i.e. entry.get()
     * == null) mean that the key is no longer referenced, so the
     * entry can be expunged from table.  Such entries are referred to
     * as "stale entries" in the code that follows.
     */
    static class Entry extends WeakReference<ThreadLocal<?>> {
        /** The value associated with this ThreadLocal. */
        Object value;
    
        Entry(ThreadLocal<?> k, Object v) {
            super(k);
            value = v;
        }
    }
    

    Entry内部维护了成员变量value,并且,Entry作为弱引用类型指向了一个ThreadLocal对象

  7. ThreadLocal.get()原理:先定位当前线程Thread,获取对应的ThreadLocalMap,之后,以当前的ThreadLocal的引用(this)为索引,在ThreadLocalMap中找对应Entry,获取对应value

    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();
    }
    
  8. ThreadLocal.ThreadLocalMap.getEntry():

    private Entry getEntry(ThreadLocal<?> key) {
       int i = key.threadLocalHashCode & (table.length - 1);
       Entry e = table[i];
       if (e != null && e.get() == key)
           return e;
       else
           return getEntryAfterMiss(key, i, e);
    }
    

    其中,e.get()返回的正是当前的ThreadLocal对象。

参考:

  1. JavaGuide:ThreadLocal解析
  2. 博客园:ThreadLocal源码解读
  3. 博客园:彻底理解ThreadLocal
  4. 博客园:kyro&PowerJob
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值