ThreadLocal原理及源码分析 - kakaka123456

1. ThreadLocal的作用

  ThreadLocal的存在和多线程是密切相关的,ThreadLocal为多线程解决并发问题提供了一个新的思路,同时ThreadLocal的设计思想也比较纯粹。

  我们都知道ThreadLocal是为多线程之间提供专属的变量、对象等等,通过ThreadLocal获取的value并不是线程共享的,而是线程自己独有的。即每个线程获取自己专有的value,互不干扰。

 

 


2. ThreadLocal的设计猜想

   满足线程的隔离:如果变量是所属对象(thread)的成员属性,可以理解为将变量和thread对象绑定在一起。

   ② 考虑到副本数据的存储。

  笔者认为ThreadLocal的设计应该是从以上两点出发的,考虑到线程间的隔离才能保证独有性,另外,每个线程独有的ThreadLocal变量需要以某种数据结构形式进行存储。既要满足隔离,又要能够存储,那么将ThreadLocal变量值与线程对象(thread)关联起来会是一个容易想到并且实现的方法。

 

 


 

 

3. ThreadLocal.get()方法源码分析

  下图是ThreadLocal的get()方法源码,首先获取当前线程对象t,通过getMap(Thread t)方法获取线程对象t的ThreadLocalMap属性,顾名思义ThreadLocalMap是专门用来存储ThreadLocal及其value值的键值对结构map,其中ThreadLocal对象为key,对应的变量值或者对象为value,获取ThreadLocalMap中key为当前ThreadLocal对象的Entry对象e,如果Entry对象e的value不为空,就说明this(当前ThreadLocal对象)已经初始化值或者通过ThreadLocal.set()方法重置过值,直接返回;否则调用ThreadLocal.setInitalValue()方法初始化。

 

 

 

 

 

 

  通过上面的ThreadLocal.get()方法的初步解析,我们对ThreadLocal和线程对象thread之间的关系以及线程对象是如何存储ThreadLocal变量应该有如下图的一个认知,例如代码:

private static ThreadLocal<Integer> numLocal = new ThreadLocal<Integer>(){
  protected Integer initialValue(){
    return 0;
  }
}

public static void main(String[] args){
  Thread[] threads = new Thread[5];
  for (int i = 0; i < threads.length; i++){
    threads[i] = new Thread(
    int x = numLocal.get().intValue();
    x+=5;
    numLocal.set(x);
    System.out.println(numLocal.get());
    );
  }
for (int i = 0; i < threads.length; i++){
  threads[i].start();
 }
}

  代码的运行结果显示五个线程的Threadlocal变量值都是5,每个线程对象都有一个自己的ThreadlocalMap属性,其中ThreadlocalMap都包含一个key为同一个numLocal的Entry对象,value就是各自set的值5.

 

 

 

 

 


 

 

4. ThreadLocal.set()方法源码分析

  同样,ThreadLocal.set()方法也是先获取当前线程对象t,然后拿到t的ThreadLocalMap属性,如果map不为空,则调用ThreadLocalMap.set方法;否则调用createMap方法初始化线程对象t的ThreadLocalMap属性并把value作为第一个Entry对象的值完成初始化。

  

 

 

  ThreadLocalMap

  ThreadLocalMap.set方法是关键,既然也是Map,那么ThreadLocalMap的set方法和HashMap其实也是差不多的。我们都知道HashMap在调用set方法时,是根据key值的散列值确定在HashMap中物理位置,如果已存在完全相等的key,则用新value覆盖掉原有的value,如果不存在完全相等的key,则先判断是否需要扩容后新增Entry元素。

  注意:这里有判断key==null;这是因为ThreadLocal属于弱引用。

 

 

posted @ 2020-03-21 17:06  少庄主-  阅读(118)  评论(0)    收藏  举报