来源:极客时间 | 深入拆解 Java 虚拟机
通常来说,当我们调用 new 指令时,它会在 Eden 区中划出一块作为存储对象的内存。由于堆空间 是线程共享的,因此直接在这里边划空间是需要进行同步的。
否则,将有可能出现两个对象共用一段内存的事故。如果你还记得前两篇我用“停车位”打的比方的 话,这里就相当于两个司机(线程)同时将车停入同一个停车位,因而发生剐蹭事故。
Java 虚拟机的解决方法是为每个司机预先申请多个停车位,并且只允许该司机停在自己的停车位 上。那么当司机的停车位用完了该怎么办呢(假设这个司机代客泊车)?
答案是:再申请多个停车位便可以了。这项技术被称之为 TLAB(Thread Local Allocation Buffer, 对应虚拟机参数 -XX:+UseTLAB,默认开启)。
具体来说,每个线程可以向 Java 虚拟机申请一段连续的内存,比如 2048 字节,作为线程私有的 TLAB。
这个操作需要加锁,线程需要维护两个指针(实际上可能更多,但重要也就两个),一个指向 TLAB 中空余内存的起始位置,一个则指向 TLAB 末尾。
接下来的 new 指令,便可以直接通过指针加法(bump the pointer)来实现,即把指向空余内存位 置的指针加上所请求的字节数。
如果加法后空余内存指针的值仍小于或等于指向末尾的指针,则代表分配成功。否则,TLAB 已经没有足够的空间来满足本次新建操作。这个时候,便需要当前线程重新申请新的 TLAB。