1、如何解决单线程程序运行中变量共享问题?

借助ThreadLocal可以做到,在单线程程序运行的任意地方都可以获取变量,这个对象叫线成的本地变量。

想要了解线成内变量共享的原理,就得看一下线成内部结构:

img

  • 线程Thread类中维护着ThreadLocalMap对象;
  • ThreadLocalMap中的Entry继承自WeakReference
  • Entry的key为被WeakReference包装的ThreadLocal对象
  • ThreadLocal对象的get\set操作的底层都是处理当前Thread所拥有的ThreadLocalMap对象

网上找了个比较形象的图:

img

2、多个线程的情况下,为什么InheritableThreadLocal可以解决线程本地变量父传子问题?

InheritableThreadLocal继承自ThreadLocal类,特殊性就体现在他的getMap方法:

1
2
3
ThreadLocalMap getMap(Thread t) {
return t.inheritableThreadLocals;
}

这里引出了线成对象的inheritableThreadLocals属性,含义就是可继承的ThreadLocalMap。那么为什么说它是可继承的呢?

通过Thread类阅读源码得知:

创建Thread对象时,会调用其init方法,其中涉及到可继承线程本地变量的代码:

1
this.inheritableThreadLocals =ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);

核心:将父线程的线程变量的引用复制一份,放到子线程维护的inheritableThreadLocals中。

这里发现两个问题:

  1. 传递的是引用,子线程修改线程变量值会影响到父线程,发生上下文污染问题。

在业务处理过程中,子线程尽量只读程变量值,不要写入。

  1. 只有新创建Thread对象才会传递线程变量

线程池化技术应用时,会复用线程,此时线程变量传递方法不会被触发。

在业务开发过程中,我们大多会用线程池来做一些异步处理逻辑,涉及到传递主线程的线程变量,此时用InheritableThreadLocal就有些力不从心。引出:阿里的TransmittableThreadLocal。

3、为什么TransmittableThreadLocal就可以解决InheritableThreadLocal复用线程时,线程变量传递的问题呢?

先来一张结构图:

img

TransmittableThreadLocal继承InheritableThreadLocal,也就是说,新建线程时,线程变量会发生传递。

重点看holder属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Note about holder:
// 1. The value of holder is type Map<TransmittableThreadLocal<?>, ?> (WeakHashMap implementation),
// but it is used as *set*.
// 2. WeakHashMap support null value.
private static InheritableThreadLocal<Map<TransmittableThreadLocal<?>, ?>> holder =
new InheritableThreadLocal<Map<TransmittableThreadLocal<?>, ?>>() {
@Override
protected Map<TransmittableThreadLocal<?>, ?> initialValue() {
return new WeakHashMap<TransmittableThreadLocal<?>, Object>();
}

@Override
protected Map<TransmittableThreadLocal<?>, ?> childValue(Map<TransmittableThreadLocal<?>, ?> parentValue) {
return new WeakHashMap<TransmittableThreadLocal<?>, Object>(parentValue);
}
};
  • holder 是 InheritableThreadLocal变量
  • holder 是 static 变量
  • value 是 WeakHashMap

参考文档:

https://github.com/alibaba/transmittable-thread-local

https://www.cnblogs.com/hama1993/p/10382523.html

https://www.cnblogs.com/hama1993/p/10400265.html

https://www.cnblogs.com/hama1993/p/10409740.html