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

  • Post author:
  • Post category:其他




(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中,那么就需要填充

    在这里插入图片描述


看一下源码:

		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 版权协议,转载请附上原文出处链接和本声明。