关于TLAB的这一部分,并不算是八股文中高频的考题,但是如果能扩展的回答这一部分,我相信肯定是面试的加分项。
什么是TLAB
TLAB(Thread-Local Allocation Buffer)是Java虚拟机(JVM)中一种用于提高对象分配性能的技术。尽管TLAB存在于堆内存中,但它实际上是每个线程私有的,因此不同线程之间的TLAB是独立的。
为什么需要TLAB
简单的讲,每当使用new关键字创建新对象,JVM 都必须为堆上的新对象留出一些内存。在单线程的情况下,这很没什么问题,因为每次只能发生一个内存分配请求,因此线程可以简单地获取下一个合适大小的块,之后线性的执行后续new请求。然而在多线程的情况下,则存在两个线程将在同一时间请求分配内存并且都将被指定到完全相同的地址的风险。但如果将分配内存变成单线程,又会使得程序出现性能瓶颈。
所以不如为每个线程保留一块堆内存区域,这块内存仅由该线程用于分配内存。通过这种方式工作,不需要同步,因为只有一个线程可以从此缓冲区中拉取。缓冲区本身以同步方式分配,但这个操作不太频繁不会造成性能瓶颈。
TLAB带来的问题
TLAB 空间是有限的。如果这个空间耗尽时,而我们继续分配内存会发生什么?
-
- 废弃当前的 TLAB,重新申请 TLAB 空间再次进行内存分配。
-
- 直接在堆内存中对该对象进行内存分配。
-
- 尝试使用垃圾收集器释放一些内存。(软弱虚引用)
-
- 无法分配内存,而是抛出错误。
解决方式
对于问题1,可能会有频繁的废弃 TLAB 申请 TLAB 的情况。TLAB 内存自己从堆中进行分配时也是需要并发控制的,而频繁的分配 TLAB就失去了TLAB本身存在的意义了。为了解决这个问题,虚拟机定义了一个 refill_waste 的值,这个值可以翻译为”最大浪费空间“。默认情况下,refill_waste的目标百分比是占TLAB容量的50%。但是可以更改
java -XX:TLABWasteTargetPercent=20 ...
当 TLAB 剩余空间不足时,
- 若请求分配的内存大于 refill_waste,会选择在堆内存中分配。
- 若请求分配的内存小于 refill_waste,会选择废弃当前的 TLAB,重新创建 TLAB 进行对象内存分配。
另外,TLAB的大小可以通过JVM参数进行调整,例如-XX:TLABSize用于设置TLAB的初始大小,-XX:+ResizeTLAB用于允许动态调整TLAB的大小。
在允许 JVM 动态确定大小的情况下,我们还可以指定-XX:MinTLABSize来给出每个线程的 TLAB 大小的下限。我们还设置-XX:MaxTLABSize作为每个线程 TLAB 可以增长到的上限。
总结
总之,TLAB是Java虚拟机中一种用于提高对象分配性能的技术,通过为每个线程分配私有的内存缓冲区,减少了线程之间的竞争,从而提高了对象分配的效率
往期文章