返回

源码阅读:剖析 ThreadLocal 的里里外外

Android

引言

ThreadLocal 作为 Java 中线程安全利器,在实际开发中扮演着至关重要的角色。它能够为每个线程创建独立的变量副本,有效避免了多线程并行访问共享资源带来的混乱。本文将通过源码解析的方式,深入剖析 ThreadLocal 的底层实现机制,带你领略其精妙的设计。

ThreadLocal 的设计原理

ThreadLocal 本质上是一种 Map 数据结构,它通过将线程与变量副本进行关联,实现了线程私有变量的概念。每个线程访问 ThreadLocal 时,都会获得自己独立的数据副本,互不干扰。这种设计巧妙地解决了多线程编程中数据共享的难题,避免了竞态条件和数据一致性问题。

ThreadLocal 源码解读

1. ThreadLocal 类

ThreadLocal 类的核心在于其 get() 和 set() 方法。get() 方法负责从当前线程中获取变量副本,如果不存在则创建一个新的副本。set() 方法则用于更新当前线程的变量副本。

public Object get() {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            return e.value;
        }
    }
    return setInitialValue();
}

public void set(Object value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
}

2. ThreadLocalMap 类

ThreadLocalMap 是 ThreadLocal 的核心实现类,它管理着每个线程的变量副本。每个线程都有一个与之关联的 ThreadLocalMap,负责存储该线程所有 ThreadLocal 变量副本。

static ThreadLocalMap getMap(Thread t) {
    return t.threadLocals;
}

3. ThreadLocalMap.Entry 类

Entry 类代表 ThreadLocalMap 中的一个条目,它包含了 ThreadLocal 变量的引用以及变量副本的值。

static class Entry extends WeakReference<ThreadLocal<?>> {
    Object value;

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

ThreadLocal 的使用场景

ThreadLocal 的典型应用场景包括:

  • 数据库连接池管理:为每个线程提供独立的数据库连接,避免多线程并发访问同一连接带来的性能问题。
  • 日志记录:为每个线程提供独立的日志记录器,方便追踪线程执行路径和定位错误。
  • 缓存管理:为每个线程提供独立的缓存,避免多线程并发访问同一缓存带来的缓存污染问题。