为什么Netty中对FastThreadLocal比ThreadLocal的性能更好,解密FastThreadLocal原理?

(1)首先看一下ThreadLocal的实现原理?

  1. 在当一个ThreadLocalMap进行get()的时候,其实是先去从当前线程获取到ThreadLocalMap对象,
  2. 然后再去【this中对应的ThreadLocal的HashCode】根据获取这个线程中的对象值。
  3. 如果出现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中,那么就需要填充
    为什么Netty中对FastThreadLocal比ThreadLocal的性能更好,解密FastThreadLocal原理?_第1张图片

看一下源码:

		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;
    }

你可能感兴趣的:(【Netty】,FastThreadLocal,ThreadLocal,ThreadLocalMap)