线程本地变量(ThreadLocal)是否分配在TLAB中?

4

我想,ThreadLocal变量是分配在线程本地分配缓冲区(TLABs)中的,我是对的吗?

我没有找到任何文件说明究竟是什么使得某些类存储在TLAB中。如果您知道,请发布链接。


我认为所有的答案都是正确的,但我不得不选择其中一个。 - Rostislav Matl
5个回答

8
我没有找到任何文件说明是什么使某些类存储在TLAB中。如果您知道,请发布链接。
实际上,该博客文章中的解释已经很清楚了:
线程本地分配缓冲区(TLAB)是Eden的一个区域,用于单个线程的分配。它使线程能够使用线程本地的顶部和限制指针进行对象分配,这比在跨线程共享的顶部指针上执行原子操作要快。
每个线程都从自己的Eden块,即堆的“第0代”部分,分配内存。几乎所有东西都在TLAB中存储一段时间——可能包括您的ThreadLocal——但它们在gen0垃圾收集后会被移出那里。TLAB旨在加快分配速度,而不是使内存对其他线程不可访问。同一篇博客中更易理解的描述请参见A little thread privacy, please

4
不是的。这是Java 1.4版本后的情况:每个线程都有一个称为“threadLocals”的字段,其中保存了映射表。每个ThreadLocal都有一个索引指向该结构,因此不使用hashCode()。可以将其想象成一个数组,每个ThreadLocal保留一个插槽索引。
当线程死亡且没有更多引用时,ThreadLocals会被GC回收。非常简单的想法。
您可以通过扩展Thread并添加一个字段来实现自己的ThreaLocal(s)来持有引用。然后将Thread转换为您自己的类并获取数据。
因此,它不是TLAB,而是像任何其他对象一样在堆中。
从历史上看,有使用静态WeakHashMap的实现方式,但访问数据非常缓慢。

Java 1.5和1.6的情况如何?我认为那里发生了很多变化。 - Rostislav Matl
1
@binary_runner - 没有任何更改,措辞是“as of”(或自从)。实际上,起初我无法理解TLAB备注,内存分配的位置与进一步分配给线程本地变量没有任何关系。ThreadLocal只是一个非常普通的Java对象,没有任何魔力(除了可能被复制的Inherited版本)。 - bestsss
因为答案大部分都与问题无关,并且似乎误解了TLAB是什么,所以被踩了。gustafc的答案才是真正的答案。 - Vsevolod Golovanov
1
@VsevolodGolovanov,第一个词('no')是正确的。答案解释了ThreadLocals的工作原理。TLAB只是年轻代中的一个小区域(仅限于当前线程),因此分配只是指针的增加。gustaf'c的答案也不完全正确 - 较大的对象从未存储在TLAB中。然而,并没有问到TLAB到底是什么。 - bestsss
即使“不”是具有误导性的,因为考虑到问题,“不”意味着“ThreadLocals不会在TLAB中分配”,而实际上应该是“ThreadLocals在这方面不会得到任何特殊处理”。Java字段和哈希码在这里都是无关紧要的。“没有引用时被GCed”也是无关紧要的。“它不是TLAB,它是堆”是具有误导性的,因为TLAB是堆的一部分。WeakHashMap甚至更加无关紧要。gustafc说“几乎所有东西都在TLAB中存储了一段时间” - “几乎所有东西”意味着“几乎所有东西”,所以他是正确的。 - Vsevolod Golovanov

2
我的理解是,TLAB用于分配所有小型到中等大小的对象。你的ThreadLocal不会有任何不同的分配方式。

1

我相信这取决于JVM实现者的自由裁量权。他们可以选择将数据放在TLAB中,也可以放在以线程ID为键的全局表中。Java语言规范往往对这些问题保持沉默,以便JVM作者可以在尽可能多样化的平台上部署Java。


1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接