为了提高程序运行的性能,现代CPU在很多方面会对程序进行优化。CPU的处理速度是很快的,内存的速度次之,硬盘速度最慢。在cpu处理内存数据中,内存运行速度太慢,就会拖累cpu的速度。为了解决这样的问题,cpu设计了多级缓存策略。
CPU分为三级缓存: 每个CPU都有L1,L2 但是L3是多核公用的。
CPU查找数据的顺序为: CPU -> L1 -> L2 -> L3 -> 内存 -> 硬盘
因为每个CPU都有自己的缓存,容易导致一种情况就是 如果多个CPU的缓存(多CPU读取同样的数据进行缓存,进行不同运算后,写入内存中)中都有同样一份数据,那这个数据要如何处理呢?已谁的为准? 这个时候就需要一个缓存同步协议了!
MESI协议 规定每条缓存都有一个状态位,同时定义了一下四种状态:
多处理器,单个CPU对缓存修改,需要通知其他CPU. 也就意味着,CPU需要控制自己的读写,还需要监听其他CPU发出的通知,从而保持最终一致性。
例如如下代码是:
指令重排:当CPU 写缓存 时发现缓存区被其他CPU占用,为了提高CPU处理性能,可能将后面的读缓存命令优先执行。
指令重排序,遵循 as-if-serial语义。即指令重排序前后,程序执行的结果不能变化。对于数据有依赖的部分,不会进行重排序。
1、CPU高速缓存的问题:
缓存中的数据与主内存的数据不是实时同步的,各个CPU间缓存的数据也不是实时同步的,在同一时间点,各个CPU所看到的的同一内存地址的数据可能是不一致的
2、CPU指令重排优化问题:
虽然遵循 as-if-serial语义,但是它是仅在单个CPU自己执行的情况下保证结果正确,多核多线程,指令逻辑无法分辨因果关联,可能出现乱序执行,导致程序结果出现错误。
写内存屏障(Store Memory Barrier):在指令后插入Store Barrier,能让写入缓存中最新数据更新写入主内存中,让其他线程可见。 强制写入主内存,这种显示调用,不会让CPU去进行指令重排序
读内存屏障(Load Memory Barrier):在指令后插入Load Barrier,可以让高速缓存中的数据失效,强制重新从住内存中加载数据。 也是不会让CPU去进行指令重排。
原文:https://www.cnblogs.com/junjiedeng/p/11679596.html