为什么需要加,为什么
因为cpu是乱序执行的,如果不加,在多线程情况下,会得到半初始化的对象
对象初始化过程:
- 开辟内存空间,所有的值成员变量赋予默认值(int short等赋予0,boolean赋予false,对象赋予null)并指向栈中对象
- 将栈中对象进行复制(dup)
- 将复制的对象进行弹出,并实现初始化(invokespecial)
- 将栈中对象弹出,并赋值给t(astore_0为this,astore1为指向的变量)
因为jvm允许对象在初始化过程中进行重排序,如果invokespecial与astore_1进行互换,则先执行赋值操作,然后代码中判断t==NULL为空,则会使用一个半初始化的对象,所以再多线程情况下,需要加volatile
volatile是如何实现的
- CPU层面:使用内存屏障 inter cpu原语(lfence mfence sfence) 或者锁总线
- 字节码层面:ACC_VOLATILE
- jvm层面:使用内存屏障
- LoadLoad屏障:
对于这样的语句Load1; LoadLoad; Load2,
在Load2及后续读取操作要读取的数据被访问前,保证Load1要读取的数据被读取完毕。 - StoreStore屏障:
对于这样的语句Store1; StoreStore; Store2,
在Store2及后续写入操作执行前,保证Store1的写入操作对其它处理器可见。 - LoadStore屏障:
对于这样的语句Load1; LoadStore; Store2,
在Store2及后续写入操作被刷出前,保证Load1要读取的数据被读取完毕。 - StoreLoad屏障:
对于这样的语句Store1; StoreLoad; Load2,
Load2及后续所有读取操作执行前,保证Store1的写入对所有处理器可见。
- LoadLoad屏障:
JVM如何规定哪些指令不可以重排序
什么是as-if-serial
不管硬件什么顺序,单线程执行的结果不变,看上去像是serial
缓存一致性如何保证
https://blog.csdn.net/qq_26222859/article/details/52235930 hsdis - HotSpot Dis Assembler windows lock 指令实现 | MESI实现(inter实现)