简介
多线程访问同一个共享变量的时候容易出现并发问题,特别是多个线程对一个变量进行写入的时候,为了保证线程安全,一般使用者在访问共享变量的时候需要进行额外的同步措施才能保证线程安全性。ThreadLocal是除了加锁这种同步方式之外的一种保证一种规避多线程访问出现线程不安全的方法,当我们在创建一个变量后,如果每个线程对其进行访问的时候访问的都是线程自己的变量这样就不会存在线程不安全问题。
ThreadLocal中有一个内部类ThreadLocalMap;而在每个Thread内部,都维护了一个ThreadLocalMap;每个线程都是对自己内部的ThreadLocalMap中进行操作。
//在Thread内部存在
ThreadLocal.ThreadLocalMap threadLocals = null;
//ThreadLocal中的方法,从当前线程中获取ThreadLocalMap
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
set
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);//从当前线程中获取ThreadLocalMap
if (map != null) {
map.set(this, value);
} else {
createMap(t, value);
}
}
get
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);//从当前线程中获取ThreadLocalMap
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
存在的问题
实际上ThreadLocalMap中使用的 key 为 ThreadLocal 的弱引用,弱引用的特点是,如果这个对象只存在弱引用,那么在下一次垃圾回收的时候必然会被清理掉。但是,value 是强引用,不会被清理,这样一来就会出现 key 为 null 的 value,会出现内存泄露的情况。