设为首页 加入收藏

TOP

Java 8 ThreadLocal 源码解析
2023-07-26 08:18:27 】 浏览:235
Tags:Java ThreadLocal 解析

目录:


我们编写一个简单的示例:


运行结果:


可以看到10个线程调用同一个ThreadLocal对象的set方法写入随机值, 然后读取到自己写入的副本。


我们从ThreadLocal.set方法开始分析:


set方法将当前线程的副本写入了一个ThreadLocalMap, map的key是当前的ThreadLocal对象。


接下来通过getMap方法分析这个ThreadLocalMap是如何维护的:


每个 Thread 对象维护了一个 ThreadLocalMap 类型的 threadLocals 字段。


ThreadLocalMap 的 key 是 ThreadLocal 对象, 值则是变量的副本, 因此允许一个线程绑定多个 ThreadLocal 对象


理解副本的管理机制后很容易理解get方法:


首先获得当前线程的ThreadLocalMap, 然后从 ThreadLocalMap 尝试获得当前 ThreadLocal 对象对应的副本。


若获取失败,则写入并返回initialValue方法定义的默认值。


Thread.threadLocals 字段是惰性初始化的。 ThreadLocal.set() 方法发现 threadLocals 为空时会调用 createMap 方法进行初始化, ThreadLocal.get()方法同样会在setInitialValue() 中调用 createMap 方法初始化 Thread.threadLocals 字段。


为了不影响读者整体了解ThreadLocal, ThreadLocalMap 的实现原理在最后一节ThreadLocalMap


InheritableThreadLocal 在子线程创建时将父线程的变量副本传递给子线程。


InheritableThreadLocal 继承了 ThreadLocal 并重写了3个方法, 它使用 Thread.inheritableThreadLocals 代替了 Thread.threadLocals 字段。


ThreadLocalMap 的构造器中实现了向子线程传递的逻辑:


Thread.init 方法调用此构造器传递 InheritableThreadLocal:


值得一提的是, ThreadLocalMap 中使用的是 WeakReference, 当 ThreadLocal 对象不再被外部引用时, 弱引用不会阻止GC因此避免了内存泄露


Entry 的 key 始终是 ThreadLocal 对象, 值则是 ThreadLocal 对象绑定的变量副本。


首先来看 ThreadLocalMap.getEntry 方法:


利用 table 大小始终为2的整数幂的特点使用位运算找到哈希槽。


若哈希槽中为空或 key 不是当前 ThreadLocal 对象则会调用getEntryAfterMiss方法:


ThreadLocalMap 使用开放定址法处理哈希冲突, nextIndex 方法会提供哈希冲突时下一个哈希槽的位置。


nextIndex 返回下一个位置, 到达末尾后返回第一个位置0.


getEntryAfterMiss 方法会循环查找直到找到或遍历所有可能的哈希槽, 在循环过程中可能遇到4种情况:


为了处理GC造成的空洞(stale entry), 需要调用expungeStaleEntry方法进行清理。


清理分为两个部分:


在执行清理时, 可能因为GC造成多个空洞因此需要循环清理。


首先来看 ThreadLocalMap.set 方法:


首先计算哈希槽的位置, 此时可能有3种情况:


接下来重点分析 replaceStaleEntry:


replaceStaleEntry 方法看上去非常复杂, 简单的说分为三部分:


cleanSomeSlots 调用 expungeStaleEntry 从位置 i 开始向后清理。


执行log2(n)次清理以取得清理效果(剩余空洞数量)和清理耗时之间的平衡。


简单看一下 rehash 的过程:


首先进行清理,若清理后sz > thresholde * 0.75将哈希表的的大小翻倍。


remove 方法和 get 方法比较类似:


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇跟我学Python GUI编程系列 - Tkin.. 下一篇跟我学Python GUI编程系列 - Tkin..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目