ThreadLocal原理

146 阅读1分钟

什么是ThreadLocal?

ThreadLocal从字面意思理解是线程本地变量。变量好理解就是存取值,那线程本地如何理解呢?又是如何实现的呢?我们来探究一下。

关于线程本地变量的理解总体来说有两点:

  • 在某个线程内使用ThreadLocal#set()设置值,只在当前线程有效不会影响其他线程
  • 在某个线程内使用ThreadLocal#get()获取值,只能获取在当前线程设置过的值

以上就是线程本地变量的理解。

实现原理

每个线程类都有一个Map结构的成员变量ThreadLocal.ThreadLocalMap threadLocals来存储每个ThreadLocal对应的value值。不管是get操作还是set操作,首先都会去获取当前线程,然后去这个线程的Map结构中去做存取操作。

调用关系:

tl.png

弱引用WeakReferencer

特性:对象在只有弱引用的情况下,JVM随时会回收该对象。

在ThreadLocalMap中Entry代码如下:

static class Entry extends WeakReference<ThreadLocal<?>> {
    /** The value associated with this ThreadLocal. */
    Object value;

    Entry(ThreadLocal<?> k, Object v) {
        super(k);
        value = v;
    }
}

Entry继承WeakReference,通过super()将当前ThreadLocal传入WeakReference。图中的T referent实际为ThreadLocal。因此在Entry中ThreadLocal在没有其他引用的情况下,可以随时被回收。

内存泄露问题

一旦Entry中的ThreadLocal实例仅被弱引用引用,就会被JVM随时回收,导致Entry中的value泄露。即value无法被回收,但实际已没有意义。

虽然源码中有些优化,但写代码的时候最好还是手动调用ThreadLocal#remove()显示删除无用的Entry对象。