ThreadLocal模式的实现机理
2016-01-18 22:25
465 查看
在早期的JDK版本中,提供了一种解决多线程并发问题的方案:java.lang.ThreadLocal类。ThreadLocal类在维护变量时,实际使用了当前线程中的一个叫做ThreadLocalMap的独立副本,每个线程可以独立修改属于自己的副本而不会相互影响,从而隔离了线程和线程,避免了线程访问实例变量发生冲突的问题。
这是JDK中Thread源码的一部分,从中我们可以看出ThreadLocalMap跟随当前的线程而存在。不同的线程Thread拥有不同的ThreadLocalMap的本地实例变量,这也就是“副本”的含义。接下来看看ThreadLocal.ThreadLocalMap是如何定义的,以及ThreadLocal如何来操作它
从上述代码中,我们看到了ThreadLocal类的大致结构和进行ThreadLocalMap的操作。我们可以得出以下结论:
1:ThreadLocalMap变量属于线程的内部属性,不同的线程拥有完全不同的ThreadLocalMap变量。
2:线程中的ThreadLocalMap变量的值实在ThreadLocal对象进行set或者get操作的时候创建的。
3:在创建ThreadLocalMap之前,会首先检查当前线程中的Thr
4000
eadLocalMap变量是否已经存在,如果不存在则创建一个;如果存在,则使用当前线程已创建的ThreadLocalMap。
4:使用当前线程的ThreadLocalMap的关键在于使用当前ThreadLocal的实力作为key进行存储。
ThreadLocal模式至少从两个方面完成了数据访问隔离,即横向隔离和纵向隔离。有了横向和纵向两种不同的隔离方式,ThreadLocal模式就能真正地做到线程安全:
1:纵向隔离——线程与线程之间的数据访问隔离。这一点由线程的数据结构保证。因为每个线程在进行对象访问时,访问的都是各个线程自己的ThreadLocalMap;
2:横向隔离——同一线程中,不同的ThreadLocal实例操作对象之间相互隔离。这一点由ThreadLocalMap在存储时采用当前ThreadLocal的实例作为key来保证。
public class Thread implements Runnable{ //这里省略了许多其他代码 ThreadLocal.ThreadLocalMap threadLocals = null; @Override public void run() { } }
这是JDK中Thread源码的一部分,从中我们可以看出ThreadLocalMap跟随当前的线程而存在。不同的线程Thread拥有不同的ThreadLocalMap的本地实例变量,这也就是“副本”的含义。接下来看看ThreadLocal.ThreadLocalMap是如何定义的,以及ThreadLocal如何来操作它
public class ThreadLocal<T> { //这里省略了许多代码 //将value的值保存到当前线程的本地变量中 public void set(T value){ //获取当前线程 Thread t = Thread.currentThread(); //调用getmap方法获取当前线程中的本地变量ThreadLocalMap ThreadLocalMap map = getMap(t); //如果ThreadLocalMap已经存在,直接使用 if(map != null){ //以当前的ThreadLocal的实力作为key,存储于当前线程的ThreadLocalMap中 //如果当前线程中定义了多个不同的ThreadLocal的实力,则它们会作为不同的key进行存储互不干扰 map.set(this, value); }else { //如果ThreadLocalMap不存在,则为当前线程创建一个新的 creatMap(t, value); } } //获取当前线程中以当前ThreadLocal实例为key的变量值 public T get(){ //获取当前线程 Thread t = Thread.currentThread(); //获取当前线程中的ThreadLocalMap ThreadLocalMap map = getMap(t); if(map != null){ //获取当前线程中以当前ThreadLocal实例为key的变量值 ThreadLocalMap.Entry e = map.getEntry(this); if(e != null) return (T)e.value; } //当map不存在时,设置初始值 return setInitialValue(); }
private T setInitialValue() { T value = initialValue(); Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); return value; }//从当前线程中获取与之对应的ThreadLocalMap ThreadLocalMap getMap(Thread d){ return t.threadLocals; } //创建当前线程中的ThreadLocalMap void creatMap(Thread t, T firstValue){ //调用构造函数生成当前线程中的ThreadLocalMap t.threadLocals = new ThreadLocalMap(this, firstValue); } //ThreadLocalMap的定义 static class ThreadLocalMap{ //这里省略了许多代码 } }}
从上述代码中,我们看到了ThreadLocal类的大致结构和进行ThreadLocalMap的操作。我们可以得出以下结论:
1:ThreadLocalMap变量属于线程的内部属性,不同的线程拥有完全不同的ThreadLocalMap变量。
2:线程中的ThreadLocalMap变量的值实在ThreadLocal对象进行set或者get操作的时候创建的。
3:在创建ThreadLocalMap之前,会首先检查当前线程中的Thr
4000
eadLocalMap变量是否已经存在,如果不存在则创建一个;如果存在,则使用当前线程已创建的ThreadLocalMap。
4:使用当前线程的ThreadLocalMap的关键在于使用当前ThreadLocal的实力作为key进行存储。
ThreadLocal模式至少从两个方面完成了数据访问隔离,即横向隔离和纵向隔离。有了横向和纵向两种不同的隔离方式,ThreadLocal模式就能真正地做到线程安全:
1:纵向隔离——线程与线程之间的数据访问隔离。这一点由线程的数据结构保证。因为每个线程在进行对象访问时,访问的都是各个线程自己的ThreadLocalMap;
2:横向隔离——同一线程中,不同的ThreadLocal实例操作对象之间相互隔离。这一点由ThreadLocalMap在存储时采用当前ThreadLocal的实例作为key来保证。
相关文章推荐
- 简单分析Java线程编程中ThreadLocal类的使用
- 实例讲解Java并发编程之ThreadLocal类
- Java多线程编程之ThreadLocal线程范围内的共享变量
- Struts2中TreadLocal设计模式详解
- Java并发编程:深入剖析ThreadLocal
- 利于ThreadLocal管理Hibernate Session
- 项目问题总结一、全局变量引起的并发问题
- 正确理解ThreadLocal
- java的ThreadLocal简介和示例
- ThreadLocal
- ThreadLocal封装Connection--事务统一管理
- ThreadLocal实现线程范围的共享变量 代码示例
- ThreadLocal知识系列总结1
- ThreadLocal
- ThreadLocal保证线程安全的原理
- ThreadLocal的奥秘
- 正确理解ThreadLocal
- ThreadLocal
- ThreadLocal设计模式
- Spring如何处理线程并发