这玩意比ThreadLocal叼多了,吓得why哥赶紧分享出来。 (3)

简介: 这玩意比ThreadLocal叼多了,吓得why哥赶紧分享出来。 (3)

所以,其实线程上绑定的数据都是放到 InternalThreadLocalMap 里面的,不管你操作什么 ThreadLocal,实际上都是操作的 InternalThreadLocalMap。


那问题来了,你觉得一个叫做 fastGet ,一个叫做 slowGet。这个快慢,指的是 get 什么东西的快慢?


image.png


对咯,就是获取 InternalThreadLocalMap。


InternalThreadLocalMap 在 InternalThread 里面是一个变量维护的,可以直接通过 InternalThread.threadLocalMap() 获得:


image.png


标号为 ① 的地方是获取,标号为 ② 的地方是设置。


都是一步到位,操作起来非常的方便。


这是 fastGet。


而 slowGet 是从 ThreadLocal 中获取:


image.png


这里的 get ,就是原生 ThreadLocal 的 get 方法,一眼望去,就复杂多了:


image.png


标号为 ① 的地方,首先计算 hash 值,然后拿着 hash 值去数组里面取数据。如果取出来的数据不是我们想要的数据,则到标号为 ② 的逻辑里面去。


那么我问你,除了这个位置上的值真的为 null 外,还有什么原因会导致我拿着计算出来的 hash 值去数组里面取数据取不到?


image.png


就是看你熟不熟悉 ThreadLocal 对 hash 冲突的处理方式了。


那么这个问题稍微的升级一下就是:你知道哪些 hash 冲突的解决方案呢?


1.开放定址法。


2.链式地址法。


3.再哈希法。


4.建立公共溢出区。


我们非常熟悉的 HashMap 就是采用的链式地址法解决 hash 冲突。


而 ThreadLocal 用的就是开放定址法中的线性探测。


所谓线性探测就是,如果某个位置的值已经存在了,那么就在原来的值上往后加一个单位,直至不发生哈希冲突,就像这样的:


image.png


上面的动图就是需要在一个长度为 7 的数组里面,再放一个进过 hash 计算后为下标为 2 的数据,但是该位置上有值,也就是发生了 hash 冲突。


于是解决 hash 冲突的方法就是一次次的往后移,直到找到没有冲突的位置。


所以,当我们取值的时候如果发生了 hash 冲突也需要往后查询,这就是上面标号为 ③ 的 while 循环代码的其中一个目的。


当然还有其他目的,就隐藏在 440 行的 expungeStaleEntry 方法里面。不是本文重点,就不多说了。


但是如果你不知道这个方法,你一定要去查阅一下相关的资料,有可能会在一定程度上改变你印象中的:用 ThreadLocal 会导致内存泄漏的风险。


至少,你可以知道 JDK 为了避免内存泄漏的问题,是做了自己的最大努力的。


好了,不扯远了,说回来。


从上面我们知道了,从 ThreadLocal 中获取 InternalThreadLocalMap 会经历如下步骤:


1.计算 hash 值。


2.判断通过 hash 值是否能直接获取到目标对象。


3.如果没有获取到目标对象则往后遍历,直至获取成功或者循环结束。


比从 InternalThread 里面获取 InternalThreadLocalMap 复杂多了。


现在你知道了 fastGet/slowGet 这个两个方法中的快慢,指的是从两个不同的 ThreadLocal 中获取 InternalThreadLocalMap 的操作的快慢。而快慢的根本原因是数据结构的差异。


好,现在我们获取到 InternalThreadLocalMap 了,接着看 set 方法:


image.png

目录
相关文章
|
7月前
|
Java
面试官:说一说CyclicBarrier的妙用!我:这个没用过...
【5月更文挑战第5天】面试官:说一说CyclicBarrier的妙用!我:这个没用过...
48 2
|
7月前
|
监控 Java 测试技术
面试准备不充分,被Java守护线程干懵了,面试官主打一个东西没用但你得会
面试准备不充分,被Java守护线程干懵了,面试官主打一个东西没用但你得会
62 1
|
Java 应用服务中间件 Spring
ThreadLocal 的使用及踩坑
ThreadLocal 的使用及踩坑
94 1
面试又被问懵了吗?不如把ThreadLocal拆开了揉碎看看
1.为什么用 ThreadLocal? 所谓并发,就是有限资源需要应对远超资源的访问。解决问题的方法,要么增加资源应对访问;要么增加资源的利用率。 所以,相信这年头做开发的多多少少,都会那么几个“线程二三招”、“用锁五六式”。 那所带来的就是多线程访问下的并发安全问题。 共享变量的访问域跨越了原始的单线程,进入了千家万户的线程眼里。谁都可以用,谁都可以改,那不就打起来了吗? 因此,防止并发问题的最好办法,就是不要多线程访问(这科技水平倒退二十年~)。ThreadLocal 顾名思义,将一个变量限制为“线程封闭”:对象只被一个线程持有、访问、修改。
|
存储 缓存 Java
终于弄明白了ThreadLocal
ThreadLocal是Thread的局部变量,用于编多线程程序,对解决多线程程序的并发问题有一定的启示作用。
162 0
终于弄明白了ThreadLocal
|
算法 安全 Java
threadlocal再温习
早时总结过《ThreadLocal解析》、《FastThreadLocal解析》 最近看一些资料的时候,又重重发现了这类,不希望再温下,许多知识点,之前已经总结了,这篇文章主要有两个问题: 1、弱引用的意义 2、如何防键冲突
245 0
threadlocal再温习
|
监控 C语言 iOS开发
小码哥底层原理之RunLoop
RunLoop是一个运行循环,保证App能够持续运行,处理各种事件,节省CPU资源,没事处理的时候就进入休眠。
174 0
小码哥底层原理之RunLoop
|
存储 安全 算法
面试:为了进阿里,死磕了ConcurrentHashMap源码和面试题(二)
在上篇《面试:为了进阿里,死磕了ConcurrentHashMap源码和面试题(一)》,研究了基础原理,以及ConcurrentHashMap数据put的流程等线程安全的,来回顾一下面试的问题点
176 0
面试:为了进阿里,死磕了ConcurrentHashMap源码和面试题(二)
|
存储 安全 算法
面试:为了进阿里,死磕了ConcurrentHashMap源码和面试题(一)
在平时中集合使用中,当涉及多线程开发时,如果使用HashMap可能会导致死锁问题,使用HashTable效率又不高。而ConcurrentHashMap在保持同步同时并发效率比较高,ConcurrentHashmap是最好的选择,那面试中也会被常常问到,那可能的问题是:
420 0
面试:为了进阿里,死磕了ConcurrentHashMap源码和面试题(一)
|
Dubbo 应用服务中间件
这玩意比ThreadLocal叼多了,吓得why哥赶紧分享出来。 (2)
这玩意比ThreadLocal叼多了,吓得why哥赶紧分享出来。 (2)
139 0
这玩意比ThreadLocal叼多了,吓得why哥赶紧分享出来。 (2)