【问题标题】:Why ThreadLocal use hash code, not array just like netty FastThreadLocal?为什么 ThreadLocal 使用哈希码,而不是像 netty FastThreadLocal 那样使用数组?
【发布时间】:2019-12-03 10:52:53
【问题描述】:

我正在阅读netty源代码,并将其与jdk源代码进行比较。 发现jdk在ThreadLocal中使用hash code,冲突多的时候比较慢。

那么为什么不用像netty中的FastThreadLocal一样使用数组,没有任何hash冲突,直接命中。

【问题讨论】:

  • 您需要询问 JDK 代码库的设计者。
  • 很多时候他们在这里回答。此外,他们中的一些人在这里很活跃,我们都想听到答案,所以我认为 SO 是解决这个问题的理想场所。例如,Brian Goetz 回答了很多此类问题供大家查看:stackoverflow.com/users/3553087/brian-goetz

标签: concurrency java-8 thread-local


【解决方案1】:

基于散列的方法可能“在有很多冲突时很慢”,但没有理由过早地假设存在很多冲突。由于“许多哈希冲突”是许多元素的标志,因此您所说的场景是线性索引方法存在更多问题。

FastThreadLocal 方法可能适用于积极使用它并创建使用它们的 FastThreadLocalThread 的特定实例的应用程序。

当 all 线程必须创建一个足够大的数组来保存 all ThreadLocal 曾经创建的实例的值时,这不会类似地工作。或者,更准确地说,一个数组通常更大,以避免每次创建 ThreadLocal 时都必须调整所有数组的大小。

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

ThreadLocal 实例可以自动收集垃圾,影响很小,这与必须遍历所有线程、重新排列它们的数组的清理方法无法相比。如果发生这种情况。我在FastThreadLocal 代码中找不到这样的清理方法。所以它似乎只是在增长。这对于标准的 JRE 解决方案显然是不可接受的。

【讨论】:

    【解决方案2】:

    @Holger 你是对的。谢谢。

    这几天看了JDK源码和netty源码,我想我明白为什么jdk用hash table而netty用common array了。

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

    但在netty中,为了搜索效率,它使用普通数组,不再自动释放内存。而netty可以手动删除一个线程的所有线程局部变量,只需使用removeAll()方法即可。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-05
      • 1970-01-01
      • 1970-01-01
      • 2017-12-26
      • 2022-06-10
      • 1970-01-01
      • 2011-10-11
      相关资源
      最近更新 更多