解密缓存一致性与指令乱序

缓存一致性与指令乱序到底是怎么回事

缓存一致性指的的在CPU、内存中数据的一致性问题,为了缓解CPU与内存之间读写数据的巨大差异问题,在CPU与内存间引入了大量的缓存,这就使得一份数据可能出现在不同的地方,也就导致了数据不一致的问题,我们称这种问题为缓存一致性问题;而指令乱序是为了提升CPU的利用率而提出的一种解决办法。

缓存

首先我们要明白缓存的出现是为了加速程序的执行过程,提升效率。为什么这样说呢?因为程序的执行是在CPU中来完成的,而程序的驻留地确实硬盘,程序需要先从硬盘加载到内存,然后再读入CPU当中才能执行,而硬盘、内存、CPU的读写数据能力相差极大(好几个数量级),为了缓解三者之间读写数据速度问题,因此引入了缓存,缓存一般在CPU当中(一般有三层缓存)。

块处理

在引入缓存后,出现了一种块处理方式(读取数据进入缓存时会将所需数据和与之相邻的数据都读入缓存【相邻数据可能为下次所需数据】)这样读入缓存的总是一块数据。

缓存一致性问题

引入缓存后,这样数据可能分布在不同的物理存储块上,这样会引发一种问题,各物理块上的数据可能存在数据不一致问题即缓存一致性问题。

解决办法

1.常用 MESI(Modified Exclusive Shared Or Invalid)(也称为伊利诺斯协议,是因为该协议由伊利诺斯州立大学提出)是一种广泛使用的支持写回策略的缓存一致性协议
2.锁总线
注:参考 缓存一致性协议

指令乱序

为了进一步提升程序的运行效率,一般在CPU层面将会允许指令重排序。那么什么是指令重排序呢?
程序中指令顺序为:
order1
order2
order3

但在执行时并不一定按照上述顺序执行,这个过程称为指令重排序。如果程序只在单线程下运行,这样执行并没有什么影响(会有个结果一致性来确保程序执行结果的准确性),但在多线程环境下这样乱序执行则无法保证结果的准确性(线程间存在共享资源时)。

禁止乱序

1.CPU层面:内存屏障 mfence、sfence、lfence,lock; 一些原子指令 如 lock
2.jvm:hanppens-before原则 和jvm层的内存屏障

注:
jvm层面的解决实际上还是得依靠虚拟机的最终实现(实际还得归到CPU层)我们应该认识到jvm只是一个中间平台,具体解决还得看CPU,它只是一种规则而已
原语:控制硬件的汇编语言
内存屏障:只是个名词而已,相当于在两条指令之间加了个隔断,上下指令不能重排序

举例

1、volatile的实现细节

字节码层面 ACC_VOLATILE

JVM层面 volatile内存区的读写 都加屏障

StoreStoreBarrier

volatile 写操作

StoreLoadBarrier

LoadLoadBarrier

volatile 读操作

LoadStoreBarrier

OS和硬件层面 不同的操作系统有不同的实现 在windows中利用 lock 指令实现 | MESI实现

2、synchronized实现细节

字节码层面 ACC_SYNCHRONIZED monitorenter monitorexit
JVM层面 C C++ 调用了操作系统提供的同步机制
OS和硬件层面 X86 : lock指令

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值