i = i+1
- 从主内存将i的值读到cpu cache中
- cpu进行i+1运行
- 将i+1后的值写入cpu cache中
- 将cpu cache的值写入主内存中
在多线程中或多CPU会引入问题,例如i初始值为5,线程一:从内存中读入到cpu cache,值为5,线程二:也从内存中读入到cpu cache,值也为5,线程一:i+1=6,线程二:i+1=6,线程一将cpu cache最终值(6)写入主内存中,线程二将cpu cache最终值(6)写入主内存中,最后主内存中的i值为6,而不是7。
为了解决缓存不一致的问题,有二种方法:
-
给数据总线加锁
我们知道,CPU与其它部件通信,是通过总线的方式来通信(CPU与内存是通过总线方式通信)
总线(数据总线、地址总线、控制总线)
当线程一与主内存通信时,先加个锁,此时线程二不能与主内存通信(获取i值),只有线程一释放锁后,线程二才可以与内存通信,这会造成一个性能问题,CPU速度会很慢,会串行化,效率很慢 -
cpu cache一致性协议
Intel MESI协议保证了主内存与cache中的副本一致性的问题。
核心思想:
(1) 当cpu写入数据的时候,如果发现该变量被共享(也就是说,在其它CPU也存在该变量副本),会发出一个信号,通知其它CPU,该变量的缓存是无效的。
(2) 当其他CPU访问变量时,重新从内存中获取。还是以i=i+1为例,cpu1: 执行i+1后,写入cpu cache,然后写入主内存,同时会通知cpu2 i值失效(此时如果cpu2正在写入cpu cache,会重新从内存读取值,之前的对i的操作指令,会重新执行一遍(比如执行i+1))。