2020年5月19日 作者 zeroheart

堆内存一定是线程共享的吗

普通情况下,我们说堆内存放实例,栈放引用,堆为共享内存,栈是私有空间。

这不是完全准确的,分配堆内存的时候,为了线程安全,需要进行[同步]操作,为了防止分配内存时候的效率比较低的问题,又时会事先开辟线程空间,TLAB,thread local allocation buffer。

分配内存时候,直接从这里面分配内存出来,其他线程只能读取和回收。

这部分空间属于Eden区,遵循垃圾回收原理,只是分配内存时候使用,提高效率。当然,如果分配对象太大,那也是无法直接利用的,所以小对象分配比大对象高效。

TLAB是一个优化方案,但也存在一些问题。

比如,一个TLAB区域大小为100k,使用了80k,还剩20k,此时如果要分配一个25k的对象。有两种可能:

1.直接从Eden区分配

2.重新开辟TLAB

以上方案也是各有利弊,如果1方案,可能存在极端情况,TLAB只剩1k,大多数对象都有在Eden分配。2方案,也可能经常要重新开辟TLAB,也是违背了我们的初衷。所以提供了可以配置的参数:refill_waste来处理,假设设置refill_waste为30k,上述例子中,25k小于30k,那么就会重新开辟TLAB,如果是要分配一个40k的对象,那么直接到Eden分配一下。

一些参数

-XX:+/-UseTLAB 开启或者关闭TLAB

-XX:TLABWasteTargetPercent TLAB占Eden的百分比,默认1%

-XX:-ResizeTLAB 默认会自动调整大小,可以手动指定 -XX:TLABSize

-XX:TLABRefillWasteFraction 默认64,表示1/64的大小作为refill_waste的大小

-XX+PringTLAB 查看TLAB情况