从 ThreadLocal 的实现看散列算法

本文深入解析Java中的ThreadLocalMap如何利用散列算法,特别是斐波那契数列来提高哈希分布的均匀性,降低冲突。通过分析源码,展示了除法散列法、平方散列法、斐波那契散列法和随机数法,并探讨了ThreadLocalMap中黄金比例与斐波那契数列的关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作者 | 小牛


640?wx_fmt=jpeg

Java 工程师,关注服务端技术 

引子

最近在看 JDK 的 ThreadLocal 源码时,发现了一段有意思的代码,如下所示。

    private final int threadLocalHashCode = nextHashCode();


   /**    
    * The difference between successively generated hash codes - turns
   
    * implicit sequential thread-local IDs into near-optimally spread
   
    * multiplicative hash values for power-of-two-sized tables.
   
    */
private static final int HASH_INCREMENT = 0x61c88647 ; /**    
    * Returns the next hash code.
   
    */
private static int nextHashCode () { return nextHashCode . getAndAdd ( HASH_INCREMENT ); }

可以看到,其中定义了一个魔法值 HASH_INCREMENT = 0x61c88647对于实例变量 threadLocalHashCode每当创建 ThreadLocal 实例时这个值都会getAndAdd(0x61c88647)

0x61c88647 转化成二进制即为 1640531527,它常用于在散列中增加哈希值。上面的代码注释中也解释到:HASH_INCREMENT 是为了让哈希码能均匀的分布在2的N次方的数组里。

那么 0x61c88647 是怎么起作用的呢?

什么是散列?

ThreadLocal 使用一个自定的的 Map —— ThreadLocalMap 来维护线程本地的值。首先我们先了解一下散列的概念。

散列(Hash)也称为哈希,就是把任意长度的输入,通过散列算法,变换成固定长度的输出,这个输出值就是散列值。

在实际使用中,不同的输入可能会散列成相同的输出,这时也就产生了冲突。通过上文提到的 HASH_INCREMENT 再借助一定的算法,就可以将哈希码能均匀的分布在 2 的 N 次方的数组里,保证了散列表的离散度,从而降低了冲突几率.

哈希表就是将数据根据散列函数 f(K) 映射到表中的特定位置进行存储。因此哈希表最大的特点就是可以根据 f(K) 函数得到其索引。

HashMap 就是使用哈希表来存储的,并且采用了链地址法解决冲突。

简单来说,哈希表的实现就是数组加链表的结合。在每个数组元素上都一个链表结构,当数据被 Hash 后,得到数组下标,把数据放在对应下标元素的链表上。

散列算法

先来说一下散列算法。散列算法的宗旨就是:构造冲突较低的散列地址,保证散列表中数据的离散度。常用的有以下几种散列算法:

除法散列法

散列长度 m, 对于一个小于 m 的数 p 取模,所得结果为散列地址。对 p 的选择很重要,一般取素数或 m

公式:f(k) = k % p (p<=m)

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值