Threadlocal原理学习
threadlocal使用场景
并发编程理解
- 原子性
一个或多个操作。要么全部执行完成并且执行过程不会被打断,要么不执行。最常见的例子:i++/i–操作。不是原子性操作,如果不做好同步性就容易造成线程安全问题。(团体作战要么全部成功要么淘汰) - 可见性
多个线程访问同一个变量,一个线程改变了这个变量的值,其他线程可以立即看到修改的值。可见性的问题,Java中有两种方式保证。一是volatile关键字,二是通过synchronized和lock,二者用不同的方式实现 - 有序性
程序执行的顺序按照代码的先后顺序执行。在代码的编译与运行时会存在乱序执行的可能。
在并发程序中当存在对临界区访问的时候,往往需要同步来保证临界区的安全,来保证程序的顺序执行,我们在学习的过程中很多时候将thread local与synchronize一起谈,很容易混淆thread local的用途
首先区分两者直接的不同
首先,ThreadLocal的设计初衷就是为了避免多个线程去并发访问同一个对象,其为每个线程创建线程的本地变量赋值,线程之间时隔离的,具体过程在后续代码中分析。
Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。即Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。所以ThreadLocal并不能代替synchronized,Synchronized的功能范围更广(同步机制)。
一个隔离创建副本,一个重在同步
ThreadLocal是JDK包提供的,它提供线程本地变量,如果创建一乐ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的一个副本,在实际多线程操作的时候,操作的是自己本地内存中的变量,从而规避了线程安全问题
与thread类的关系
Thread类中有两个变量threadLocals和inheritableThreadLocal,
- 1 threadloacal中set方法会完成thread类中threalocals变的初始化
- set方法源码
public void set(T value) {
//(1)获取当前线程(调用者线程)
Thread t = Thread.currentThread();
//(2)以当前线程作为key值,去查找对应的线程变量,找到对应的map
ThreadLocalMap map = getMap(t);
//(3)如果map不为null,就直接添加本地变量,key为当前定义的ThreadLocal变量的this引用,值为添加的本地变量值
if (map != null)
map.set(this, value);
//(4)如果map为null,说明首次添加,需要首先创建出对应的map
else
createMap(t, value);
}
每个线程的本地变量不是存放在ThreadLocal实例中,而是放在调用线程的ThreadLocals变量里面(前面也说过,该变量是Thread类的变量)。也就是说,ThreadLocal类型的本地变量是存放在具体的线程空间上,其本身相当于一个装载本地变量的工具壳,通过set方法将value添加到调用线程的threadLocals中,当调用线程调用get方法时候能够从它的threadLocals中取出变量。
- 继续分析get 等方法