这玩意比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

目录
相关文章
|
Dubbo Cloud Native 网络协议
【Dubbo3技术专题】「服务架构体系」第一章之Dubbo3新特性要点之RPC协议分析介绍
【Dubbo3技术专题】「服务架构体系」第一章之Dubbo3新特性要点之RPC协议分析介绍
297 1
|
安全 前端开发 Java
SpringBoot接口如何设计防篡改、防重放攻击
Spring Boot 防篡改、防重放攻击本示例主要内容请求参数防止篡改攻击基于timestamp方案,防止重放攻击使用swagger接口文档自动生成API接口设计API接口由于需要供第三方服务调用,所以必须暴露到外网,并提供了具体请求地址和请求参数,为了防止被别有用心之人获取到真实请求参数后再次发起请求获取信息,需要采取很多安全机制。
4565 0
|
9月前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是"将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。创建型模式分为5种:单例模式、工厂方法模式抽象工厂式、原型模式、建造者模式。
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
10月前
|
数据管理 大数据 OLAP
AnalyticDB核心概念详解:表、索引与分区
【10月更文挑战第25天】在大数据时代,高效的数据库管理和分析工具变得尤为重要。阿里云的AnalyticDB(ADB)是一款完全托管的实时数据仓库服务,能够支持PB级数据的实时查询和分析。作为一名数据工程师,我有幸在多个项目中使用过AnalyticDB,并积累了丰富的实践经验。本文将从我个人的角度出发,详细介绍AnalyticDB的核心概念,包括表结构设计、索引类型选择和分区策略,帮助读者更有效地组织和管理数据。
458 3
|
SQL Cloud Native 关系型数据库
云原生数据仓库使用问题之分组优化如何实现
阿里云AnalyticDB提供了全面的数据导入、查询分析、数据管理、运维监控等功能,并通过扩展功能支持与AI平台集成、跨地域复制与联邦查询等高级应用场景,为企业构建实时、高效、可扩展的数据仓库解决方案。以下是对AnalyticDB产品使用合集的概述,包括数据导入、查询分析、数据管理、运维监控、扩展功能等方面。
|
编解码 Dubbo NoSQL
由浅入深理解RPC架构设计
🌴🌴经常听到大家说不同项目之间调用使用HTTP方式,同一个项目内不同服务之间调用使用RPC方式。今天就来学习一下`RPC框架`,RPC框架由哪些部分组成又是如何一步一步设计出来的。
838 0
由浅入深理解RPC架构设计
|
存储 算法 Java
JVM垃圾收集-ZGC的染色指针
垃圾收集是回收以前分配的内存的机制, 以便将来的内存分配可以重用它。
1143 0
JVM垃圾收集-ZGC的染色指针
|
算法 安全 Java
JVM垃圾回收-三色标记
垃圾收集是回收以前分配的内存的机制, 以便将来的内存分配可以重用它。
309 1
JVM垃圾回收-三色标记
|
SQL 存储 缓存
MySQL中:一条update语句是怎样执行的
这次来详细介绍一下在MySQL中一条更新语句的详细执行流程
1052 1
MySQL中:一条update语句是怎样执行的
|
运维 Dubbo 安全
Dubbo3 源码解读-宋小生-4:Dubbo的扩展机制
Dubbo3 已经全面取代 HSF2 成为阿里的下一代服务框架,2022 双 11 基于 Dubbo3 首次实现了关键业务不停推、不降级的全面用户体验提升,从技术上,大幅提高研发与运维效率的同时地址推送等关键资源利用率提升超 40%,基于三位一体的开源中间件体系打造了阿里在云上的单元化最佳实践和统一标准,同时将规模化实践经验与技术创新贡献开源社区,极大的推动了开源技术与标准的发展。 本文是 Du
534 0
Dubbo3 源码解读-宋小生-4:Dubbo的扩展机制