美文网首页程序员
正确解读ThreadLocal

正确解读ThreadLocal

作者: SilenceDut | 来源:发表于2016-07-15 17:52 被阅读287次

在Android的消息机制中,Handler是非常重要的一部分,而完全要理解Handler的机制,首先应该理解ThreadLocal,关于ThreadLocal,见到很多地方叫做线程本地变量,也有些地方叫做线程本地存储,其实意思差不多。可能很多人都知道ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量,这样的词容易让人产生误解或者迷惑。
首先,从最新的ThreadLocal源码看,ThreadLocal并未创建任何本地变量,也没有copy副本的存在,是直接用的Thread对象的成员变量,因此叫做"线程变量帮助类"其实更合适,它的作用就是拿到当前线程对象的Object[] value数组,然后进行存储和取值,因为这属于每个线程的内部变量数组,因此也不存在共享,所以也就没有线程安全的问题。
先看一个例子:

ThreadLocal例子.png

例子可以看出不同的线程得到的值是不同的,说明ThreadLocal可以使同一个变量在不同的线程里有不同的值,为什么同一个变量在不同的线程的会表现出不同的值呢,源码说明一切:

先看set方法:

set(T value).png 得到当前Thread对象的Values值.png

可以看出ThreadLocal的Values引用直接指向Thread的localValues值。看下put()方法的实现。

put.png

很好理解,可以简单看做用单个数组来实现的简易hashmap的,hashmap的key是当前ThreadLocal对象的hash值与当前数组长度的求模运算,存入在数组的index位置,value就是当前的存入值,这个值总是放在index+1的位置,可以理解为index和index+1这两个位置就是hashmap的Entry。好像在jdk1.7之前就是用hashmap来实现的,原理都是一样的。这样是Thread类更加的轻量化。

get()

通过上面的分析get函数也很好理解了。先得到当前线程对象的Values对象,然后得到Values中的Object[] table数组,从数组中取出值。

ThreadLocal 实例通常建议是用 private static 字段,至于原因想不太清楚。但这不是绝对的,在Android的事件机制Looper中

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

这就不是一个private变量,至于静态

public static @Nullable Looper myLooper() {    
    return sThreadLocal.get();
}

因为需要静态方法获取Looper对象,所以就必须是静态的的吧。看到一种说法是设置static 是因为ThreadLocal支持线程范围生命周期的变量,所以不属于类的属性。不知是否有些牵强。
关于内存泄露的问题

/** Weak reference to this thread local instance. */
private final Reference<ThreadLocal<T>> reference = new WeakReference<ThreadLocal<T>>(this);

因为是软引用持有,所以不会存在内存泄露的问题。但确定不需要使用的时候最好调用remove()方法来释放内存。

简单总结

判断是否需要对资源进行同步的判断准则是,当前获取(get)资源是否会有其他线程进行修改(set)或者当前进行修改的资源是否会有其他线程可以获取。

  • synchronized——串行访问
  • volatile——主内存刷新,不存在线程副本
  • ThreadLocal——线程空间内的全局变量

相关文章

  • 正确解读ThreadLocal

    在Android的消息机制中,Handler是非常重要的一部分,而完全要理解Handler的机制,首先应该理解Th...

  • 解读ThreadLocal

    1 什么是ThreadLocal ThreadLocal,翻译过来,就是"线程本地变量",它是从JDK1.2开始提...

  • ThreadLocal源码分析

    首先通过问题去看源码 ThreadLocal通过空间换取线程变量安全的说法正确吗 ThreadLocal为什么说会...

  • ThreadLocal 源码分析

    ThreadLocal 没有“线程安全”一说,正确来讲 ThreadLocal 实现是不存在线程/资源竞争的。 T...

  • ThreadLocal源码解读

    一.threadlocal概述 顾名思义线程本地存储,如果定义了一个threadlocal对象,每个线程往这个th...

  • ThreadLocal源码解读

      在学习Handler消息机制中Looper源码时看到ThreadLocal这个类,发现它很强大并且很方便的实现...

  • ThreadLocal 源码解读

    ThreadLocal是什么 ThreadLocal提供了线程的局部变量,每个线程访问独立的变量副本,实现了线程的...

  • ThreadLocal源码解读

    ThreadLocal的场景是用来隔离各个线程的局部变量,各个线程之间的数值互不干扰。先查看个例子: 执行的结果如...

  • ThreadLocal源码解读

    每个线程都有一个ThreadLocal线程本地变量,各个线程本地变量互不干扰。TreadLocalMap类型的变量...

  • ThreadLocal 源码解读

    ThreadLocal 翻译就是线程局部变量,就是这个变量只存在于当前的线程,只存在于当前的线程,那么完美解决了并...

网友评论

    本文标题:正确解读ThreadLocal

    本文链接:https://www.haomeiwen.com/subject/rhbyjttx.html