Android ThreadLocal源码分析

ThreadLocal是一个用于将对象线程封闭的类,每个线程都能访问到相互隔离的对象副本,这样访问这个对象就一定是线程安全的。大概原理就是HashMap<Thread,Object>,但是具体实现的差异还是很大的。之前因为理解偏差,看了源码半天没搞懂,看了网上的源码分析反而更是一头雾水,昨晚仔细看了一下,总算是明白了。

我看的是23的sdk的源码,这个版本的sdk的ThreadLocal跟Oracle提供的那个JDK里面的实现还是有差异的。JDK里面的ThreadLocal里面的静态类是一个Map,而ThreadLocal里面的静态类则不是Map。先不说细节,上一张图:

ThreadLocal结构图

ThreadLocal有个静态类叫Values,Values内部有个数组,起到类似HashMap的作用。这个数组的第i位放ThreadLocal的弱引用,第i+1位则用来放值。 第i位是如何确定的呢,通过ThreadLocal的hash值,这个hash值又是通过hashCounter得到的:

hashCounter

注意到这里TheradLocal是key,而非Thread,映射关系也并非保存在ThreadLocal中,而是保存在每个Thread中。ThreadLocal所关心的仅仅是自己的hash值和弱引用。Thread内部保存着这个内部类的引用:

Thread

看看ThreadLocal的get()方法:

  @SuppressWarnings("unchecked")
    public T get() {//假如一个新线程去访问主线程里创建的threadlocal.get()
        // Optimized for the fast path.
        Thread currentThread = Thread.currentThread();
        Values values = values(currentThread);//看看自己保存的Values引用
        if (values != null) { //不为空,则可以根据ThreadLocal的hash值去找到对应的值了
            Object[] table = values.table;
            int index = hash & values.mask;
            if (this.reference == table[index]) {//key为弱引用
                return (T) table[index + 1];//返回value
            }
        } else { //线程保存的hash数组为null ,那么要初始化这个hash数组
            values = initializeValues(currentThread);
        }

        return (T) values.getAfterMiss(this);
    }

ThreadLocal的set()方法:

    public void set(T value) {//要为这个线程的对象副本赋值了
        Thread currentThread = Thread.currentThread();
        Values values = values(currentThread);
        if (values == null) {//本线程的hash数组未初始化
            values = initializeValues(currentThread);
        }
        values.put(this, value);//放入
    }

Values静态类里面的逻辑略复杂一点,我先不分析了。其实ThreadLocal的源码还是相对简单的,我昨晚看了那么久主要还是理解错了,一开始以为一定有一个Map保存在ThreadLocal内部,结果看了半天越看越糊涂。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容