ThreadLocal线程安全的奥秘

ThreadLocal,存储线程内部的数据,线程独享,没有线程安全问题,它是如何做到这些的呢?原因就是数据存储在Thread实例中,每一个Thread的实例拥有ThreadLocal.ThreadLocalMap threadLocals 成员,该成员是包共享的。ThreadLocal的set方法把数据存储在当前线程的threadLocals map中,保证每个线程数据的独立。

Thread 代码:

/* ThreadLocal values pertaining to this thread
 * by the ThreadLocal class. */                
ThreadLocal.ThreadLocalMap threadLocals = null;

ThreadLocal set 代码:

/**                                                                    
 * Sets the current thread's copy of this thread-local variable        
 * to the specified value.  Most subclasses will have no need to       
 * override this method, relying solely on the {@link #initialValue}   
 * method to set the values of thread-locals.                          
 *                                                                     
 * @param value the value to be stored in the current thread's copy of 
 *        this thread-local.                                           
 */                                                                    
public void set(T value) {                                             
    Thread t = Thread.currentThread();                                 
    ThreadLocalMap map = getMap(t);                                    
    if (map != null)                                                   
        map.set(this, value);                                          
    else                                                               
        createMap(t, value);                                           
}                                                                      

ThreadLocal的初始化化方法: protected T initialValue()

缺省返回null,可以被override,线程第一次使用 get() 方法访问变量时将调用此方法,但如果线程之前调用了 set(T) 方法,则不会对该线程再调用 initialValue 方法。通常,此方法对每个线程最多调用一次,但如果在调用 get() 后又调用了 remove(),则可能再次调用此方法。

ThreadLocal的get方法:

/**                                                              
 * Returns the value in the current thread's copy of this        
 * thread-local variable.  If the variable has no value for the  
 * current thread, it is first initialized to the value returned 
 * by an invocation of the {@link #initialValue} method.         
 *                                                               
 * @return the current thread's value of this thread-local       
 */                                                              
public T get() {                                                 
    Thread t = Thread.currentThread();                           
    ThreadLocalMap map = getMap(t);                              
    if (map != null) {                                           
        ThreadLocalMap.Entry e = map.getEntry(this);             
        if (e != null)                                           
            return (T)e.value;                                   
    }                                                            
    return setInitialValue();                                    
}   
*                                  
 * @param  t the current thread     
 * @return the map                  
 */                                 
ThreadLocalMap getMap(Thread t) {   
    return t.threadLocals;          
}                                                                                                

你可能感兴趣的:(threadLocal)