ThreadLocal源码解析

  synchronized这类线程同步的机制可以解决多线程并发问题,在这种解决方案下,多个线程访问到的,都是同一份变量的内容。为了防止在多线程访问的过程中,可能会出现的并发错误。不得不对多个线程的访问进行同步,这样也就意味着,多个线程必须先后对变量的值进行访问或者修改,这是一种以延长访问时间来换取线程安全性的策略。

  而ThreadLocal类为每一个线程都维护了自己独有的变量拷贝。每个线程都拥有了自己独立的一个变量,竞争条件被彻底消除了,那就没有任何必要对这些线程进行同步,它们也能最大限度的由CPU调度,并发执行。并且由于每个线程在访问该变量时,读取和修改的,都是自己独有的那一份变量拷贝,变量被彻底封闭在每个访问的线程中,并发错误出现的可能也完全消除了。对比前一种方案,这是一种以空间来换取线程安全性的策略。

ThreadLocal允许每个线程与持有数值的对象关联在一起,ThreadLocal提供了get和set方法,为每个使用它的线程提供了维护一份单独的拷贝。所以get总是返回当前线程通过set获取到的最新值.

  ThreadLocal的实现原理为内部创建了一个静态内部类,它是用来存放ThreadLocal及其关联值的集合。

static class ThreadLocalMap  

  在ThreadLocalMap中又含有一个静态内部类Entry,并有一个私有变量 private Entry[] table;用来存储Entry类

/**
*Entry类用来存储ThreadLocal以及其关联的value.
*该类继承了WeakReference<ThreadLocal>,表示一旦没有指向key(ThreadLocal)的强引用,Entry类会被立即回收
*/ 
 static class Entry extends WeakReference<ThreadLocal> {
            /** 值和ThreadLocal相关联. */
            Object value;

            Entry(ThreadLocal k, Object v) {
                super(k);
                value = v;
            }
        }

  在ThreadLocal中主要有get()和set两个方法,其中set方法是设置当前线程ThreadLocal对应的值,其源码为

    public void set(T value) {
        Thread t = Thread.currentThread();//获取当前运行的线程
        ThreadLocalMap map = getMap(t); //获取当前线程中ThreadMap 
        if (map != null)
        //如果map不为空则将ThreadLocal及value添加到map中
            map.set(this, value);
        else
            createMap(t, value); //如果map为空,创建新的map,并ThreadLocal及value添加到map中
    }

  通过查看Thread类的源码可知,Thread类中含有成员ThreadLocalMap,通过调用getMap(t)方法,可以获取当前执行线程中的ThreadLocalMap成员。

1  /* ThreadLocal values pertaining to this thread. This map is maintained
2      * by the ThreadLocal class. */
3     ThreadLocal.ThreadLocalMap threadLocals = null;
 1  /**
 2      * Get the map associated with a ThreadLocal. Overridden in
 3      * InheritableThreadLocal.
 4      *
 5      * @param  t the current thread
 6      * @return the map
 7      */
 8     ThreadLocalMap getMap(Thread t) {
 9         return t.threadLocals;
10     }

  ThreadLocal中的get()方法主要用来获取当前执行线程中ThreadLocal对应的值,源码为:

 1    /**
 2      * Returns the value in the current thread's copy of this
 3      * thread-local variable.  If the variable has no value for the
 4      * current thread, it is first initialized to the value returned
 5      * by an invocation of the {@link #initialValue} method.
 6      *
 7      * @return the current thread's value of this thread-local
 8      */
 9     public T get() {
10         //获取当前线程
11         Thread t = Thread.currentThread();
12 
13         /**仍然通过getMap方法来获取当前线程中存储Threadlocal及其关联值集合*/
14         ThreadLocalMap map = getMap(t);
15         if (map != null) {
16             ThreadLocalMap.Entry e = map.getEntry(this);
17             if (e != null)
18                 return (T)e.value;//如果不为空则返回当前值
19         }
20         //如果为空则返回ThreadLocal初始化的值
21         return setInitialValue();
22     }    

 

posted @ 2014-08-03 22:44  程序猿进化之路  阅读(259)  评论(0)    收藏  举报