ThreadLocal的set方法是否有死循环风险!!!
2020-02-23 本文已影响0人
Tomy_Jx_Li
背景
今天在看《码出高效》的时候,看到ThreadLocal,跟着书中内容进行源码阅读。通过查看set源码,突然发现,好像这里会发生死循环,但是……
1.首先查看set方法

2.查看ThreadLocalMap的set方法

如果这里e != null,满足条件,能进入循环,且k == key和k == null都不满足条件。那么就会导致一直执行e = tab[i = nextIndex(i, len)]这一行代码,这是为什么呢?查看方法nextIndex的源码可知
3.nextIndex方法

很明显,nextIndex方法是可以一直执行下去的,所以进入死循环。
4.不可能发生
但是,这一切却不可能发生,为什么呢!!!
首先因为ThreadLocalMap是一个Map,而该Map是有一个存储的阈值的,也就是threshold属性,当存储的数值达到阈值上线,就会进行扩容的。那么就需要查看下threshold的赋值情况了。
5.threshold的赋值

threshold的赋值只有这一个地方可以进行,所以一个ThreadLocalMap的存储上线就是其数组长度的三分之二。并且很重要的一个点ThreadLocalMap解决hash冲突是使用的开放寻址法,和HashMap的链表法不一样。
所以通过threshold,才使得这个看上去会发生死循环风险的代码能正常执行下去。