(1)首先看一下ThreadLocal的实现原理?
- 在当一个ThreadLocalMap进行get()的时候,其实是先去从当前线程获取到ThreadLocalMap对象,
- 然后再去【this中对应的ThreadLocal的HashCode】根据获取这个线程中的对象值。
- 如果出现hash冲突的话,就会使用hash线性探测算法,知道找到没有冲突的槽位
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
这个就是进行使用ThreadLocal的hash值进行hash探测解决hash冲突的
这里是利用当前ThreadLocal对象的HashCode与上ThreadLocalMap的Entry数组的长度
private Entry getEntry(ThreadLocal<?> key) {
int i = key.threadLocalHashCode & (table.length - 1);
Entry e = table[i];
if (e != null && e.get() == key)
return e;
else
return getEntryAfterMiss(key, i, e);
}
补充:
-
在ThreadLocalMap中的key其实存的并不是当前线程对象,而是利用当前ThreadLocal对象的HashCode与上ThreadLocalMap的Entry数组的长度算出来的一个Entry数组中的下标
(2)通过实战深入理解ThreadLocal的核心思想和用法?
- ThreadLocalMap是定义在ThreadLocal类内部的私有类,它是采用“开放定址法”解决冲突的hashmap。key是ThreadLocal对象。当调用某个ThreadLocal对象的get或put方法时,首先会从当前线程中取出ThreadLocalMap,然后查找对应的value:
参考文章:
大佬文章
(3)然后看一下FastThreadLocal的实现原理和优点关键点?
-
首先FastThreadLocal的第一个优化点是直接使用了常量作为下标 -
第二点优点就是消除了缓存行的伪共享来提高效率 -
有一点需要注意的是使用FastThreadLocal是需要配合FastThreadLocalThread线程才能发挥功能的,不然会退化到普通线程的性能,在进行get()的时候源码会进行instanceof
介绍一下什么是伪共享:
-
解决伪共享的解决方案,就是比如原来是把多个变量都缓存到同一行的cache line中,现在为了防止多个变量频繁交互修改,从而导致其他本来没有修改的变量也失效了,然后每次都需要从主存中去获取,这样效率就大大降低了,所以,需要把每一个变量单独放到cache line中,那么就需要填充
看一下源码:
public final V get() {
InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.get(); // 1
这一步是效率高的核心,直接用数组来代替之前的hash运算
Object v = threadLocalMap.indexedVariable(index); // 2
if (v != InternalThreadLocalMap.UNSET) {
return (V) v;
}
V value = initialize(threadLocalMap); // 3
registerCleaner(threadLocalMap); // 4
return value;
}
=======================InternalThreadLocalMap=======================
public static InternalThreadLocalMap get() {
Thread thread = Thread.currentThread();
if (thread instanceof FastThreadLocalThread) {
return fastGet((FastThreadLocalThread) thread);
} else {
return slowGet();
}
}
private static InternalThreadLocalMap fastGet(FastThreadLocalThread thread) {
InternalThreadLocalMap threadLocalMap = thread.threadLocalMap();
if (threadLocalMap == null) {
thread.setThreadLocalMap(threadLocalMap = new InternalThreadLocalMap());
}
return threadLocalMap;
}
public Object indexedVariable(int index) {
Object[] lookup = indexedVariables;
return index < lookup.length? lookup[index] : UNSET;
}
版权声明:本文为qq_36520235原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。