Q:为何说可以通过ThreadLocal实现在同一进程内维护同一数据在不同线程中各自的值并且互不干扰?
Example:
从上面的三个线程分别打印结果为:主线程为true,thread_1为false,thread_2为null(为null的原因是在线程2中并没有mBoolThreadLocal的备份)。
分析其中的原因要从ThreadLocal源码中找原因。
首先每一个线程的内部都持有一个ThreadLocal.ThreadLocalMap对象(Key(ThreadLocal)->Value(CopyObj)), 以ThreadLocal作为key, 是因为一个线程内可以new出很多个ThreadLocal对象, 每一个ThreadLocal对象都会对应一个备份Obj的值, 而每一个ThreadLocalMap则缓存了当前线程所有的备份Objs. 需要理解的是一个ThreadLocal对应一个CopyObj, 一个线程内可以创建多个ThreadLocal对象。
//源码分析的部分我觉得我写的不够好,一位小米工程师写的很好了所以我直接贴上他的回答吧~
解密ThreadLocal
——-以上的博文分析的版本有更新
thread-localMap结构已经被替换成Valeus容器,虽然这个容器依旧起的是一个映射的作用却不是一个真正的map结构,实际上是一个Object[]数组结构->table。而table的尺寸是等于entry的两倍。一个entry占据两个table[]的单位,前者存放ThreadLocal,后者存放value。因为table的length初始值为16*2而每次的扩容收缩都是移位操作故table.length一定是2的幂。
ThreadLocal.set():
综上,每当一个thread对自己的ThreadLocal.Values对象进行put(Object value)操作时,首先会去遍历存储表中是否含有空的位置,如果有空位置标记为TOMBSTONE,此标记可让下一次fill对象的时候直接填进来,而不需要占用新的位置。当然在执行clean之前还会进行一次rehash判断,检查当前的live entry数量是否大于capacity/2。是的话直接执行一次扩容操作(期间已经清理了TOMBSTONE的空间就不需要继续去clean了)