ThreadLocal理解

ThreadLocal理解

ThreadLocal,是一个用于解决多线程并发问题的实现方案:当使用ThreadLocal维护变量时,ThreadLocal为每一个线程提供一份线程独立变量

Thread,表示线程,实质是通过CPU的快速切换实现并发的效果
通过Thread.currentThread()方法获取当前Thread对象,这个方法是一个native方法,是需要操作系统实现

源码

  • Thread

    class Thread implements Runnable {
        
        /* 与此线程有关的ThreadLocal值。该映射由ThreadLocal类维护 */
        ThreadLocal.ThreadLocalMap threadLocals = null;
        
    	/**
         * 返回对当前正在执行的线程对象的引用.
         */
        public static native Thread currentThread();
    }
    
  • ThreadLocal

    public class ThreadLocal<T> {
        /** 获取哈希值相关,目的是将对象均匀分布在数组中*/
    	private final int threadLocalHashCode = nextHashCode();
        private static final int HASH_INCREMENT = 0x61c88647;
        private static int nextHashCode() {
            return nextHashCode.getAndAdd(HASH_INCREMENT);
        }
        
        /** 获取ThreadLocal中对应当前Thread的对象*/
        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、Thread的对象 */
        public void set(T value) {
            Thread t = Thread.currentThread();
            ThreadLocalMap map = getMap(t);
            if (map != null)
                map.set(this, value);
            else
                createMap(t, value);
        }
        
        /** 获取当前Thread对应ThreadLocalMap,即threadLocals对象 */
        ThreadLocalMap getMap(Thread t) {
            return t.threadLocals;
        }
        
        /** 获取当前Thread对应ThreadLocalMap,即threadLocals对象 */
        private T setInitialValue() {
            T value = initialValue();
            Thread t = Thread.currentThread();
            ThreadLocalMap map = getMap(t);
            if (map != null)
                map.set(this, value);
            else
                createMap(t, value);
            return value;
        }
        
        /** 为当前Thread创建ThreadLocalMap,并设置初始值,key为当前ThreadLocal对象 */
        void createMap(Thread t, T firstValue) {
            t.threadLocals = new ThreadLocalMap(this, firstValue);
        }
        
        
        static class ThreadLocalMap {
        	private Entry[] table;
            
            
            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);
            }
            
            
            static class Entry extends WeakReference<ThreadLocal<?>> {
                /** 与此ThreadLocal关联的值. */
                Object value;
    
                Entry(ThreadLocal<?> k, Object v) {
                    super(k);
                    value = v;
                }
            }
        }
    }
    

源码分析结论

ThreadLocal实现方式
	- 实质上每个Thread都会有维护一个threadLocals,用作存储当前线程操作对象
	- ThreadLocalMap实质是通过一个Entry[]来存储线程操作对象
		- 每个ThreadLocal都通过nextHashCode函数获取threadLocalHashCode
			- 通过与数组长度取模运算,实现元素在数组中的均匀分布
				- threadLocalHashCode & (len-1)
			- 如果位置冲突,则使用临近的一个空位置存储
	- ThreadLocal只是操作了当前Thread的threadLocals,将自身作为key值实现数据的存储
	
总结:ThreadLocal只是一个操作者,而真正的数据维护在Thread的threadLocals中
posted @ 2021-03-22 23:29  南极洲小卡  阅读(39)  评论(0)    收藏  举报