回答
Java 对象主要是在堆中分配,但是堆内存是线程共享的,当多个线程同时申请堆内存时,则可能会产生竞争关系,那如何保证内存分配的线程安全呢?有两种解决方案:
- 使用 CAS。失败重试,即申请内存失败后再次重新申请,但是这种方案在高并发场景下性能低下。
TLAB
。JVM 采用TLAB
策略来保证分配内存时的线程安全。
TLAB
,即 Thread-Local Allocation Buffer,是为每个线程分配内存的一种机制,其目的是提高 JVM 内存分配的效率,减少在多线程环境下的竞争。
其工作原理是:每个线程在 Java 堆中预先分配一小块内存,这块内存是该线程的私有线程。当该线程需要给对象分配内存时,就直接在自己这块"私有"内存中分配,当这部分内存区域用完之后,再重新分配新的"私有"内存。
这样,每个线程在其私有的 TLAB 中分配内存,就可以避免多个线程在 Java 堆内存中争夺锁,从而降低了线程间的竞争。
其分配过程如下图:
- JVM 默认开启
TLAB
功能,我们也可以使用-XX: +UseTLAB
来显示开启 - 使用
-XX:+PrintTLAB
可以跟踪TLAB
的使用情况 - 我们可以通过
-XX:TLABSize
参数指定分配给每一个线程的TLAB
空间的大小 TLAB
仅作用于新生代的Eden
,它是从Eden
中划分出来的一部分内存,在使用完毕后需要退回给Eden