【并发】ThreadLocal的实现方式

ThreadLocal 的实现涉及到 Java 内部的许多细节,主要依赖于每个线程维护的一个 ThreadLocalMap 对象。以下是 ThreadLocal 实现的关键部分:

1. ThreadLocal

ThreadLocal 类本身提供了一些公共方法,如 get()set()remove(),这些方法实际上是对 ThreadLocalMap 进行操作。

public class ThreadLocal<T> {
    // 初始化 ThreadLocal 值
    protected T initialValue() {
        return null;
    }

    // 获取当前线程的 ThreadLocal 值
    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();
    }

    // 设置当前线程的 ThreadLocal 值
    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

    // 移除当前线程的 ThreadLocal 值
    public void remove() {
        ThreadLocalMap m = getMap(Thread.currentThread());
        if (m != null)
            m.remove(this);
    }

    // 初始化值并放入 ThreadLocalMap
    private T setInitialValue() {
        T value = initialValue();
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
        return value;
    }

    // 获取当前线程的 ThreadLocalMap
    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }

    // 创建 ThreadLocalMap
    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

    // 内部类 ThreadLocalMap
    static class ThreadLocalMap {
        // ...
        // 定义 Entry
        static class Entry extends WeakReference<ThreadLocal<?>> {
            Object value;
            Entry(ThreadLocal<?> k, Object v) {
                super(k);
                value = v;
            }
        }
        
        // 存储 Entry 的数组
        private Entry[] table;
        
        // 初始化
        ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
            table = new Entry[INITIAL_CAPACITY];
            int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
            table[i] = new Entry(firstKey, firstValue);
            size = 1;
            setThreshold(INITIAL_CAPACITY);
        }
        
        // 获取 Entry
        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);
        }
        
        // 设置值
        private void set(ThreadLocal<?> key, Object value) {
            Entry[] tab = table;
            int len = tab.length;
            int i = key.threadLocalHashCode & (len-1);
            
            for (Entry e = tab[i];
                 e != null;
                 e = tab[i = nextIndex(i, len)]) {
                ThreadLocal<?> k = e.get();
                
                if (k == key) {
                    e.value = value;
                    return;
                }

                if (k == null) {
                    replaceStaleEntry(key, value, i);
                    return;
                }
            }
            
            tab[i] = new Entry(key, value);
            int sz = ++size;
            if (!cleanSomeSlots(i, sz) && sz >= threshold)
                rehash();
        }
        
        // 移除 Entry
        private void remove(ThreadLocal<?> key) {
            Entry[] tab = table;
            int len = tab.length;
            int i = key.threadLocalHashCode & (len-1);
            for (Entry e = tab[i];
                 e != null;
                 e = tab[i = nextIndex(i, len)]) {
                if (e.get() == key) {
                    e.clear();
                    expungeStaleEntry(i);
                    return;
                }
            }
        }
        
        // 其他方法...
    }
}

2. Thread 类中的 ThreadLocalMap

每个线程都有一个 ThreadLocalMap,这个 ThreadLocalMapThread 类中的一个成员变量,用于存储该线程的 ThreadLocal 变量。

public class Thread implements Runnable {
    // 每个线程都持有一个 ThreadLocalMap
    ThreadLocal.ThreadLocalMap threadLocals = null;
    
    // 其他线程相关方法和属性...
}

3. ThreadLocalMap 实现

ThreadLocalMapThreadLocal 类的一个静态内部类,用于存储线程局部变量。它使用 ThreadLocalhashCode 作为键,将值存储在一个 Entry 数组中。Entry 继承自 WeakReference,使用弱引用来防止内存泄漏。

  • 弱引用ThreadLocalMap 中的 Entry 使用弱引用来引用 ThreadLocal 实例,避免内存泄漏。当一个 ThreadLocal 实例不再被其他强引用引用时,GC 可以回收它,而不需要显式地移除 Entry

4. 哈希算法和冲突解决

ThreadLocalMap 使用哈希算法将 ThreadLocal 实例的 hashCode 映射到 Entry 数组的索引位置。如果发生哈希冲突,则使用线性探测法解决冲突。

5. 内存管理

ThreadLocalMap 使用 WeakReference 以及定期清理过期条目来管理内存。通过这些机制,可以防止内存泄漏,即使线程长期存在,已经不再使用的 ThreadLocal 变量也可以被 GC 回收。

总结

ThreadLocal 通过每个线程维护一个独立的 ThreadLocalMap,并使用弱引用来管理线程局部变量,从而提供线程安全的变量存储。它在多线程编程中非常有用,尤其是在需要确保线程独立性的场景中。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值