https://juejin.cn/post/7434855558354894860
我们都知道java对象通常分配在堆空间中。当多个线程同时向堆空间分配对象时,可能会出现线程一分配了一块内存,而线程二也试图分配到同一块内存的情况,从而引发内存分配的资源竞争问题。那么java堆上的对象内存分配到底是不是线程安全的呢
其实呀,JVM是保证了java堆上对象内存分配的线程安全问题了的,那么JVM具体是通过那些机制来保证堆上对象内存分配的线程安全的呢?
TLAB(Thread Local Allocation Buffer)机制机制原理:TLAB 全称是 Thread Local Allocation Buffer,即线程本地分配缓冲区。每个线程在启动时,可以通过参数配置提前在堆内存中分配一块自己的内存空间。例如线程一在启动时,就可以分配一块线程内存。当这个线程要分配对象的时候,直接在自己的这块空间去分配对象即可。
有一个参数可以控制 TLAB 的开启,开启后线程启动时会从堆内部画一小块内存空间给它独自使用。还有一个参数 tarab size 可以指定分配给线程的空间大小。
优势:多个线程在分配对象时,在自己的内存空间进行分配,不存在资源竞争加锁的问题,提供了性能。
CAS(Compare And Swap)机制机制原理: 当 TLAB 耗尽时,JVM 内部会用到 CAS 机制来分配内存。如果线程一把自己的 TLAB 空间用完了还需要内存,而其他线程也可能需要分配新的空间,这时就会用到 CAS 机制。 假设线程一和线程二现在都要用新的内存,线程一如果先使用,可能会修改内存指针。线程一和线程二在使用前可能取的都是这个指针的值,当线程一先分配完内存后,会把这个指针的值修改。如果线程二再去分配使用时,发现指针值已变,就需要重新取这一块起始的指针值,然后从这个指针开始的下一大块内存空间进行分配。
优势:CAS 机制是比较并交换的无锁机制,性能比较高。
分代收集机制: 不同生命周期的对象放在不同的分代中,在一定程度上也可以保证线程安全。因为只在当前分代内部多个线程去竞争时,才会有线程安全问题。