堆内存一定是线程共享的吗
普通情况下,我们说堆内存放实例,栈放引用,堆为共享内存,栈是私有空间。
这不是完全准确的,分配堆内存的时候,为了线程安全,需要进行[同步]操作,为了防止分配内存时候的效率比较低的问题,又时会事先开辟线程空间,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情况