大家好,又见面了,我是你们的朋友全栈君。
(一)计算机内存模型
大家都知道在计算机执行程序的时候每条指令都是在cpu中执行的,那么执行指令的同时势必会有读取和写入的操作,那么这样就引申出了一个问题。那么在程序运行时数据的存储是在计算机中的主存中(物理内存)的而内存的读取和写入的速度与cpu的执行指令速度相比差距是很大的,这样就造成了与内存交互时程序执行效率大大降低,因此在cpu中就有了高速缓存。
也就说计算机cpu在执行指令时将主存中的数据复制到高速缓存中,将结果运算完毕后在将运算结果刷新到主存中。废话不多说看图说话
那么大家也看到了计算机cpu会将运算数据复制到高速缓存中。但是这样如果在单线程是没有问题的(单核多线程也是有问题的)本次只是针对多核多线程讨论so 不废话举个栗子
代码语言:javascript复制i=i 1;
当同时有两个线程执行这段代码其实我们想得到的结果是2但是呢计算机cpu可不会按照你想的来,其实它会这样执行,假设我们现在有AB两个线程,同时读取了这段代码(假设i变量初始值为0),同时将变量复制到了高速缓存,A线程将数据执行完毕后将变量刷新到主存中i=1,而B线程也同时执行完毕将变量也刷新到主存中i=1,但是AB变量在运算时读取的都是高速缓存的,AB线程的高速缓存是互相不知道其中的值的,那么这样就引申出了缓存一致性问题。
为了解决缓存一致性问题有两种解决办法:
(1)通过总线加LOCK锁的方式
(2)通过缓存一致协议
早期的cpu中是通过在总线加锁来解决缓存不一致的,因为计算机cpu通信是通过总线来执行的,如果在总线上面加锁的话就阻塞来其他cpu对该变量的访问,如上面的代码在程序执行时总线发出lock指令,那么只有在这段代码执行完毕后其他cpu才能读取变量执行相应的指令,这样就解决了缓存一致性问题。
但是上面的方式会有一个问题,由于在锁住总线期间,其他CPU无法访问内存,导致效率低下。
所以就出现了缓存一致性协议。最出名的就是Intel 的MESI协议,MESI协议保证了每个缓存中使用的共享变量的副本是一致的。它核心的思想是:当CPU写数据时,如果发现操作的变量是共享变量,即在其他CPU中也存在该变量的副本,会发出信号通知其他CPU将该变量的缓存行置为无效状态,因此当其他CPU需要读取这个变量时,发现自己缓存中缓存该变量的缓存行是无效的,那么它就会从内存重新读取。
未完待续
参考资料:http://www.cnblogs.com/dolphin0520/
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/138294.html原文链接:https://javaforall.cn