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