为什么ThreadLocal使用哈希码,而不是像netty FastThreadLocal那样使用数组?

时间:2019-07-25 08:12:29

标签: concurrency java-8 thread-local

我正在阅读netty源代码,并将其与jdk源代码进行比较。 我发现jdk在ThreadLocal中使用哈希码,当有很多冲突时它很慢。

所以为什么不像netty中的FastThreadLocal一样使用数组,没有任何哈希冲突,然后直接命中。

2 个答案:

答案 0 :(得分:2)

基于散列的方法可能“在存在许多冲突时变慢”,但是没有理由过早地假定存在许多冲突。由于“许多哈希冲突”是许多因素的标志,因此您所谈论的是线性索引方法存在更多问题的情况。

对于积极使用FastThreadLocal的应用程序并创建使用它们的特定FastThreadLocalThread实例的应用程序,可能会很好。

all 线程必须创建足够大的数组以容纳曾经创建的 all ThreadLocal实例的值时,此方法无法正常工作。或者,更确切地说,通常是一个甚至更大的数组,以避免每次创建ThreadLocal时都要重新调整所有数组的大小。

您可以通过延迟扩展数组来降低成本,但是当为所有索引小于该值的本地ThreadLocal#800设置值时,甚至没有不再存在,因为该方案不支持自动清除。

ThreadLocal实例可以自动收集垃圾,几乎没有影响,这与必须遍历所有线程并重新排列其数组的清理方法不具有可比性。如果那发生了。我在FastThreadLocal代码中找不到这种清除方法。因此,它似乎只是在增长。对于标准的JRE解决方案,这显然是不可接受的。

答案 1 :(得分:0)

@Holger你是对的。谢谢。

这些天,我阅读了JDK源代码和netty源代码后,我想我明白了为什么jdk使用哈希表,而netty使用公共数组。

JDK使用哈希表,因为当不再使用线程局部变量时,可以释放变量,并且可以调整哈希表的大小以避免内存泄漏。因此,JDK使用WeakReference作为条目来自动释放内存,并使用0x61c88647减少哈希冲突。

但实际上,为了提高搜索效率,它使用通用数组,并且不再自动释放内存。 netty可以手动删除线程的所有线程局部变量,只需使用removeAll()方法即可。