一、前置知识
缓存一致性协议:每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了,当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置成无效状态,当处理器对这个数据进行修改操作的时候,会重新从系统内存中把数据读理器缓存里。
内存屏障:现代计算机为了提高效率,当前线程在分配的时间片下不够用时,在能保证结果不会改变的时候,将后边执行时间短的命令提前执行。内存屏障是为了在特定情况下保证程序顺序执行而的一个指令。
原子操作:不可中断的一个或一系列操作。
缓存行:缓存中可以分配的最小单位。为了提高性能而在cpu内置的一块存储区域。
二、volatile
volatile是轻量级的synchronized,它在多处理器开发中保证了共享变量的“可见性”。
在对volatile关键字修饰的变量进行修改时,会在指令前增加Lock前缀
Lock前缀的指令在多核处理器下会引发了两件事情:
1)将当前处理器缓存行的数据写回到系统内存。LOCK#信号确保在声言该信号期间,处理器可以独占任何共享内存。如果访问的内存区域已经缓存在处理器内部,则不会声言LOCK#信号。它会锁定这块内存区域的缓存并回写到内存,并使用缓存一致性机制来确保修改的原子性,此操作被称为“缓存锁定”,缓存一致性机制会阻止同时修改由两个以上处理器缓存的内存区域数据。
2)这个写回内存的操作会使在其他CPU里缓存了该内存地址的数据无效。
三、synchronized
JVM基于进入和退出Monitor对象来实现方法同步和代码块同步。monitorenter指令是在编译后插入到同步代码块的开始位置,而monitorexit是插入到方法结束处和异常处,JVM要保证每个monitorenter必须有对应的monitorexit与之配对。任何对象都有一个monitor与之关联,当且一个monitor被持有后,它将处于锁定状态。线程执行到monitorenter指令时,将会尝试获取对象所对应的monitor的所有权,即尝试获得对象的锁。
四、对象内存布局
对象头
由 XX:+UseCompressedClassPointer 控制进行压缩
Mark Word
类型指针
XX:+UseCompressedClassPointer,将8个字节压缩为4个字节
实例数据
由 -XX:+UseCompressedOops 控制进行压缩,将对象引用8个字节压缩为4个字节
数组长度
4字节,数组对象特有
对齐填充
将对象所占空间补充为8的倍数