「这是我参与2022首次更文挑战的第18天,活动详情查看:2022首次更文挑战」。
对象分配并发安全问题
Java程序天生是多线程的,如果一个创建对象的程序处于多线程并发执行,那么就会产生线程安全问题,试想:如果A线程准备将对象分配在堆内存的x_0001处,此时B线程也执行到创建对象,在申请空间的时候发现x_0001处未分配…后续的问题就不用说了。那么JVM是怎么解决这个问题的呢?
1.CAS无锁机制
这种方式最易想到,采用锁机制进行线程并发问题可以很好地解决。
但是毕竟全局使用CAS锁机制,如果在高并发情况而且创建对象的时间比较长,那么这种方式性能的问题就凸显了出来,于是第二种方式孕育而生。
2.TLAB(本地线程分配缓冲Thread Local Allocation Buffer)
TLAB顾名思义,JVM将每个线程在堆中预先分配一块私有内存空间 ,这用每个独立的线程都有属于自己的Buffer,如果有对象需要分配那么就会在自己的Buffer中创建对象,当Buffer用满了以后就会重新分配缓冲区,此时这个阶段是需要CAS锁机制保证安全。JVM可以通过制定启动参数-XX:+/-UseTLAB来指定。
内存空间初始化
对象分配内存完成之后,JVM需要将对象的实例数据赋予默认值,比如对象类型赋值null,基本类型赋值默认值,例如int -> 0,boolean -> false。
设置
JVM还需要堆对象进行必要的设置,例如这个对象属于哪个类的实例、GC分代年龄等,这些信息存储在对象头中。需要注意的是对象的哈希码并不是在此刻计算(实际上的哈希码会延后到真正调用Object::hashCode()方法时才计算赋值)
初始化
执行构造方法,实例变量赋真实值。