我们都知道,ThreadLocal
提供了一种将资源绑定到当前线程的手段,实现资源在线程之间的隔离。通过set
和get
方法能够进行资源的存取操作。
从它的方法来看,仿佛ThreadLocal
就是个容器,为我们保存资源,实际上是这样的吗?它到底是怎么做到线程隔离的?
问题描述
定义一个ThreadLocal
对象local,线程t1和t2均会使用local.set
放置资源,t1,t2
在通过get
获取时又只会拿到自己set
进去的资源,这种线程隔离是怎么做到的?明明只有一个ThreadLocal
对象为多个线程服务,但却保持了线程间的隔离
实现原理
ThreadLocal并不是个容器,它本身不会存储任何资源
,如果它是一个容器,任何一个线程均能访问容器内的所有资源,无法做到线程隔离。
ThreadLocal
中有个内部类ThreadLocalMap
,key为ThreadLocal
对象,value为资源内容。
ThreadLocalMap的实例保存在Thread中
,这是线程隔离的关键,即每个Thread都会持有独属于自己的一个ThreadLocalMap
,线程通过ThreadLocal.set
保存的资源实际上保存在这个ThreadLocalMap
中。
ThreadLocal.get
在使用ThreadLocal.get
时,其执行步骤如下:
ThreadLocal
会获取到当前的线程thread
- 从
thread
中拿到这个thread
独有的ThreadLocalMap
- 从
ThreadLocalMap
取得自己这个ThreadLocal
对象对应的Entity
- 返回这个
Entity
的value
ThreadLocal.set
在使用ThreadLocal.set
时,其执行步骤如下:
ThreadLocal
会获取到当前的线程thread
- 从
thread
中拿到这个thread
独有的ThreadLocalMap
- 向
Map
中添加key
为自身ThreadLocal
对象、value
为资源的Entity
从上面可以看到,ThreadLocal
有两个功能
- 资源标记,
ThreadLocal
对象为key
,资源为value
,作为一个资源的标记 - 执行者,它从线程自身中拿到对应的资源并还给线程
ThreadLocal适用场景
- 多线程环境下,将共享变量变成多个线程独有的副本,将共享变成不共享,解决并发问题
- 作为一种传递数据的手段,如果某个资源很多地方都会用到,而每次创建又很麻烦或者很占资源,可以直接放到
ThreadLocal
中,其他地方直接从ThreadLocal
中取得即可