Dubbo 内部实现了InternalThreadLocal 其读写速度比一般的要快很多
ThreadLocal
ThreadLocal的用来存储线程间局部变量。其内部维护了一个ThreadLocalMap,ThreadLocalMap是一个定制化的hashmap。每个Thread对应一个ThreadLocalMap,其原理可以参考 ThreadLocal
InternalThreadLocal 介绍
InternalThreadLocal用法和ThreadLocal基本一致。但是其内部的数据结构是不同的。
ThreadLocal内部是维护了ThreadLocalMap也就是一个hashmap,每一个ThreadLocal对应的slot都是需要经过hash计算出来,并且也要解决hash碰撞等等,是一种空间时间折中的方案。
InternalThreadLocal内部是维护一个ThreadLocalMap,而ThreadLocalMap是一个有序的数组,每次增加都会获取下一个slot的位置,然后填充,每次remove的时候将slot置为UNSET。但是InternalThreadLocal并没有对slot重新排位的操作,这就意味着如果remove的次数比较多,空间利用率会比较低,但是如果remove操作不多,那么将会带来极大速度提升,如果仅仅测试set/get,我的i5 8G 机器相比ThreadLocal大概有20倍提升。算是一种空间换取时间的方案。
InternalThreadLocal 源码解读
进入几个关键方法看下
get
1 | public final V get() { |
继续进入ThreadLocalMap
1 | public static InternalThreadLocalMap get() { |
从上面的代码看出来,InternalThread其实和ThreadLocalMap是一一对应的关系
其中get方法分了fastGet/slowGet
fastGet是通过InternalThreadLocal直接读取其内部变量InternalThreadLocalMap
slowGet通过原生的ThreadLocal中获取InternalThreadLocalMap
set
1 | public final void set(V value) { |
1 | // thread local map |
到这里就明确了,InternalThreadLocal内部维护的其实是一个有序的数组
remove
1 | public final void remove() { |
1 | // InternalThreadLocalMap |
remove操作就是把threadlocal在threadlocalmap中的数组置为UNSET
InternalThreadLocal中VARIABLES_TO_REMOVE_INDEX的变量,这个会存一个在InternalThreadLocalMap中的索引,这个索引对应了一个Set,而这个Set中存储了所有的非UNSET的InternlThreadLocal变量
这个Set主要是用在removeAll函数中
1 | // InternalThreadLocalMap |