引言
ThreadLocal提供了线程私有的局部变量,可以在整个线程存活的过程中随时取用,从而减少了在同一个线程内多个函数或者组件之间公共变量传递的复杂度。同时,由于ThreadLocal变量的线程私有性,故不存在并发线程安全的问题。
要满足上述特性,需要解决3个问题:
- 与线程绑定,实现私有性;
- 提供合适的容器,方便变量的存取;
- 设计合理的垃圾回收机制,避免内存泄露。
实现原理
为解决前2个问题,JDK最早期的设计是在ThreadLocal类内部维护一个线程安全的Map,线程的ID作为Map的key,实例对象作为Map的value,进而达到各个线程值隔离的效果。
该种中心化的模式下,通过Map的key来进行线程的绑定,而Map同时又作为变量的容器,ThreadLocal类需要处理复杂的多线程同步及变量回收问题,笨重且效率较低,所以后期JDK换了一种去中心化的方式,将管理权下放给了下面的各个线程,下面通过源码来阐述。
首先看set方法:
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
可以看到,set方法主要分为以下两个步骤: