文章目录
1.硬件基础
👉🏿 CPU、MESI、CacheLine、WriteCombining、Fence
1.1 存储器的层次结构
CPU内部:L0-寄存器,L1-高速缓存,L2-高速缓存
CPU共享:L3-高速缓存,L4-主存,L5-磁盘,L6-远程文件存储
👉🏿 离CPU越近,容量越小,但速度越快!
1.2 多线程数据一致性的硬件支持(硬件层数据一致性问题)
总线锁 - 锁粒度太大(老cpu)
MESI: - 缓存锁
缓存一致性协议很多:
Inter用的是MESI:https://www.cnblogs.com/z00377750/p/9180644.html
CPU会给每一个缓存行的内存进行一个状态标记:Modified、Exclusive、Shared、Invalid
然后针对每种状态进行不同的操作处理,目的是:让多颗CPU中的缓存数据保持一致性
有些内容是无法使用缓存锁的,比如数据内容过大,这时只能使用总线锁来保证数据的一致性
现代CPU的数据一致性实现 = 缓存锁(MESI)+ 总线锁
1.3 缓存行技术:cpu优化执行效率的改进
CacheLine是CPU读取缓存是的基本单位!
CacheLine目前为64Byte(和计算机的操作系统有关系)
e.g:cpu要读取一个int类型(4byte),此时一次的交互数据量 = 1CacheLine = 64Byte - 缓存行对齐
2. CPU级别的内存屏障
fence - 指令执行的有序性保障
sfence:sfence指令前的写操作,必须在sfence指令后的写操作前执行完成 | store-fence
lfence:lfence指令前的读操作,必须在lfence指令后的读操作前执行完|load-fence
mfence:mfence指令前的读写操作,必须在mfence指令后的读写操作前执行完|mix-fence
fence前后的指令,不允许进行重排序(cpu按照fence划分的区域,来执行指令)
3. JVM级别的有序性保障
3.1 JVM的有序性规范(JSR133):
LoadLoad屏障:
对于这样的语句Load1; LoadLoad; Load2
在Load2及后续读取操作要读取的数据被访问前,保证Load1要读取的数据被读取完毕。
StoreStore屏障:
对于这样的语句Store1; StoreStore; Store2
在Store2及后续写入操作执行前,保证Store1的写入操作对其它处理器可见。
LoadStore屏障:
对于这样的语句Load1; LoadStore; Store2
在Store2及后续写入操作被刷出前,保证Load1要读取的数据被读取完毕。
StoreLoad屏障:
对于这样的语句Store1; StoreLoad; Load2
在Load2及后续所有读取操作执行前,保证Store1的写入对所有处理器可见。
3.2 volatile实现细节
1. 字节码层面
access_flags:ACC_VOLATILE
2. JVM层面
volatile内存区的读写,都加屏障
StoreStoreBarrier;volatile写操作;StoreLoadBarrier;
LoadLoadBarrier;volatile读操作;LoadStoreBarrier;
3. OS和硬件层面(每个硬件实现方式不一样)
Windows的实现可以看看
hsdis - HotSpot Dis Assembler - 一个工具(虚拟机反汇编)
windows lock 指令实现 | MESI实现
4. synchronized实现细节
1.字节码层面
access_flags:ACC_SYNCHRONIZED – sync方法
一条指令monitorenter,2条指令monitorexit – sync代码块
2.JVM层面
C C++实现,调用操作系统提供的同步机制(linux、windows)
3.OS和硬件层面
x86:lock cmpxchg / 各种lock指令参数
cmpxchg - compare and exchange
参考博客