ThreadLocalMap中hash冲突的解决

这篇具有很好参考价值的文章主要介绍了ThreadLocalMap中hash冲突的解决。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. ThreadLocal的set方法

作用是设置当前线程绑定的局部变量:

  1. 首先是获取当前线程,并根据当前线程获取一个Map。
  2. 如果获取的Map不为空,则将参数设置到Map中(当前ThreadLocal的引用作为key)。这里调用了ThreadLocalMap的set方法。
  3. 如果Map为空,则给线程创建Map,并设置初始值。这里调用了ThreadLocalMap的构造方法。

2. ThreadLocalMap的构造方法

ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue)

构造函数首先创建一个长度为16的Entry数组,然后计算出firstKey对应的索引,存储到table中,并设置size和threshold。

int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1)

2.1 &前表达式

private final int threadLocalHashCode = nextHashCode();

private static int nextHashCode(){
	return nextHashCode.getAndAdd(HASH_INCREMENT);
}

// AtomicIntger是一个提供原子操作的Intger类,通过线程安全的方式操作加减,适合高并发情况下的使用
private static AtomicIntger nextHashCode = new AtomicInteger();
// 特殊的hash值
private static final int HASH_INCREMENT = 0x61c88647;

这里定义了一个AtomicInteger类型,每次获取当前值并加上HASH_INCREMENT, HASH_INCREMENT = 0x61c88647。

这个值跟斐波那契数列(黄金分割数)有关,其主要目的是为了让哈希码能均匀的分布在2的次方的数组里,也就是Entry[] table中,这样做可以尽量避免hash冲突。

2.2 &后表达式

计算hash的时候里面采用了hashCode & (size - 1)的算法,这相当于取模运算hashCode % size的一个更高效的实现。

正是因为这种算法,我们要求size必须是2的整次幂,这也能保证索引在不越界的前提下,使得hash发生冲突的次数减小。

3. ThreadLocalMap中的set方法

代码执行流程:

  1. 首先还是根据key计算出索引i,然后查找位置上的Entry。
  2. 若是Entry已经存在并且key等于传入的key,那么这时候直接给这个Entry赋新的value值。
  3. 若是Entry存在,但是key为null,则调用replaceStaleEntry来更换这个key为空的Entry。
  4. 不断循环检测,直到遇到为null的地方,这时候要是还没在循环过程中return,那么就在这个null的位置新建一个Entry,并且插入,同时size增加1。

最后调用cleanSomeSlots, 清理key为null的Entry,最后返回是否清理了Entry。

接下来再判断sz是否>=threshold达到了rehash的条件,达到的话就会调用rehash函数执行一次全表的扫描清理。

4. 使用线性探测法来解决哈希冲突

该方法一次探测下一个地址,直到有空的地址后插入,若整个空间都找不到空余的地址,则产生溢出。

举个例子,假设当前table的长度为16,也就是说如果计算出来key的hash值为14,如果table[14]上已经有值,并且其key与当前key不一致,那么就发生了hash冲突,这个时候将14加1得到15,取table[15]进行判断,这个时候如果还是冲突会回到0,取table[0],以此类推,直到可以插入。

按照上面的描述,可以把Entry[] table看成一个环形数组。

参考资料:ThreadLocalMap中hash冲突的解决文章来源地址https://www.toymoban.com/news/detail-407156.html

到了这里,关于ThreadLocalMap中hash冲突的解决的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Redis(三)存储原理与数据模型(hash冲突、渐进式rehash)

    Redis(一)原理及基本命令(柔性数组) Redis(二)网络协议和异步方式(乐观锁悲观锁) Redis(三)存储原理与数据模型(hash冲突、渐进式rehash) Redis跳表 Redis是key-value的结构,其中value包含:字典,双向链表,压缩列表,跳表,整数数组,动态字符串。 其中redis中各valu

    2024年02月16日
    浏览(47)
  • Java学数据结构(4)——散列表Hash table & 散列函数 & 哈希冲突

    1.散列表,key,散列函数; 2.哈希冲突的解决; 3.string中的hashCode; 查找树ADT,它允许对元素的集合进行各种操作。本章讨论散列表(hash table)ADT,不过它只支持二叉查找树所允许的一部分操作。散列表的实现常常叫作散列(hashing)。散列是一种用于以常数平均时间执行插入、删除和

    2024年02月10日
    浏览(55)
  • node:internal/crypto/hash:71 this[kHandle] = new _Hash(algorithm, xofLen); 解决方法

    Error: error:0308010C:digital envelope routines::unsupported B站尚硅谷 尚医通 项目 P101 在 nuxt 使用 npm run dev时出现: 在发现使用 set NODE_OPTIONS=–openssl-legacy-provider 不好使的情况下 解决方法: 给 node.js 降版本,最好不使用17及以上版本 这里使用 node16.19.0 链接: Index of /download/release/v16.1

    2024年02月11日
    浏览(43)
  • 【解决Git提交冲突的方法】

    在多人协作的项目中,经常会遇到提交冲突的情况。当多个开发者同时修改了同一个文件的相同部分时,Git会提示提交冲突。下面是解决提交冲突的方法: 1. 理解冲突 当提交冲突发生时,首先要理解冲突发生的原因。查看冲突的文件,Git会在文件中标记出发生冲突的部分,

    2024年02月05日
    浏览(61)
  • 解决哈希冲突的几种方法

    哈希函数是一个映像,把任意长度的输入,通过Hash算法变换成固定长度的输出,这个输出就是Hash值; 当两个不同的输入,产生了同一个输出值即为哈希冲突 开放寻址法的核心思想是, 如果出现了散列冲突,我们就重新探测一一个空闲位置,将其插入 。比如,我们可以使用

    2024年01月17日
    浏览(38)
  • 【Git】TortoiseGit代码冲突解决方法

    冲突场景:User1和User2修改、拉取相同文件 User1修改文件C内容,提交并推送,成功; User2修改文件C内容,拉取,提示合并错误。 冲突分析: 此时文件状态还未显示冲突,因为本地文件只是修改,并未提交到本地暂存区;而此时从远程拉取的文件已保存在暂存区,但又无法和

    2024年01月20日
    浏览(74)
  • 多人协作gitee出现的冲突与解决方法

    在gitee创建仓库后, 在电脑上进行克隆版本库,并在版本库中创建文件test.txt, 然后多人同时对该test.txt进行版本更新操作, 由于所有人在完成更新操作时都无法保证及时通知其他人, 而且推送更新后的文件给远程服务器时,如果有先于自己推送的,自己这边就会提示推送失

    2023年04月18日
    浏览(51)
  • git代码合并、git解决冲突的方法?

    Git是一种分布式版本控制系统,它提供了多种方法来合并代码和解决冲突。下面是两个常见的场景以及对应的操作步骤: 合并分支 当我们在一个项目中有多个分支时,需要将不同分支中的代码合并到一起。假设我们有一个主分支master和一个开发分支dev,现在需要将dev分支合

    2024年02月02日
    浏览(56)
  • androidx和v4包资源冲突解决方法

    错误类似 (androidx.core:core:1.10.0) 和 (com.android.support:support-compat:24.2.0) 表示资源重复,不知调用androidx包下面的,还是v4包下面的 2.1 在gradle.properties中只添加了android.useAndroidX=true(表示当前项目启用 AndroidX) 2.2 添加android.enableJetifier=true(表示将依赖包也迁移到AndroidX,将项目中用到

    2024年02月02日
    浏览(52)
  • 克隆虚拟机之后网络IP冲突解决方法

        虚拟机的克隆是快速创建虚拟机的一种方法,但是克隆之后却带来了一些问题。如果被克隆虚拟机配置了静态IP地址,那么克隆之后的虚拟机会与之前的虚拟机出现IP地址、MAC地址和UUID的冲突,那么本文则阐述如何解决上述冲突。     问题的解决分为两个步骤:1、修

    2024年01月25日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包