什么是缓存一致性问题?如何解决?

当程序在运行过程中,会将运算需要的数据从主存复制一份到cup的高速缓存当中,那么cpu进行计算时就可以直接从它的高速缓存读取数据和向其中写入数据,当运算结束后,再将高速缓存中的数据刷新到主存当中。举个简单的例子,比如下面这段代码:

i=i+1
  • 1

当线程执行这个语句时,会先从缓存当中读取i的值,然后复制一份到高速缓存当中,然后CPU执行命令对i进行加1操作,然后将数据写入高速缓存。最后将高速缓存中的最新的值刷新到主存当中。

这个代码在单线程中运行时没有任何问题的,但是在多线程中运行就会有问题了。在多核CPU中,每条线程可能运行于不同的CPU中,因此每个线程运行时有自己的高速缓存(对单核CPU来说,其实也会出现这种问题,只不过是以线程调度的形式来分别执行的)。我们以多喝CPU为例。

可能存在下面一种情况:初始时,两个线程分别读取i的值存入各自所在的CPU的高速缓存当中,然后线程1进行加1操作,然后把i的最新值1写入到内存。此时线程2的高速缓存当中i的值还是0,进行加1操作之后,i的值为1,然后线程2把i的值写入内存。

最终结果i的值是1,而不是2.这就是缓存一致性问题。通常称这种被多个线程访问的变量为共享变量。

解决缓存一致性问题的方法有一下2种:

  1. 通过在总线加LOCK#锁的方式
  2. 通过缓存一致性协议

在早期的CPU当中,是通过在总线上加LOCK#锁的形式来解决缓存不一致的问题。因为CPU和其他部件进行通信都是通过总线来进行的,如果对总线加LOCK#锁的话,也就是说阻塞了其他CPU对其他部件访问,从而使得只有一个CPU能使用这个变量的内存。比如上面例子中,如果一个线程在执行i=i+1,如果在执行这段代码的过程中,在总线上发出了LOCK#锁的信号,那么只有等待这段代码完全执行完毕之后,其他CPU才能从变量i所在的内存读取变量,然后进行相应的操作。这样就解决了缓存不一致问题。

但是上面的方式会有一个问题,由于在锁住总线期间,其他CPU无法访问内存,导致效率低下。

所以就出现了缓存一致性协议。该协议保证了每个缓存中使用的共享变量的副本是一致的。它的核心思想是:当CPU向内存写入数据时,如果发现操作的变量是共享变量,即在其他CPU中也存在该变量的副本,会发出信号通知其他CPU将该变量的缓存置为无效状态,因此当其他CPU需要读取这个变量时,发现自己缓存中缓存行是无效的,那么它就会从内存重新读取。java中的volatile就是该协议的实现,volatile的实现原理可参见volatile底层实现

posted @ 2019-03-19 21:10  strawqqhat  阅读(710)  评论(0编辑  收藏  举报
#home h1{ font-size:45px; } body{ background-image: url("放你的背景图链接"); background-position: initial; background-size: cover; background-repeat: no-repeat; background-attachment: fixed; background-origin: initial; background-clip: initial; height:100%; width:100%; } #home{ opacity:0.7; } .wall{ position: fixed; top: 0; left: 0; bottom: 0; right: 0; } div#midground{ background: url("https://i.postimg.cc/PP5GtGtM/midground.png"); z-index: -1; -webkit-animation: cc 200s linear infinite; -moz-animation: cc 200s linear infinite; -o-animation: cc 200s linear infinite; animation: cc 200s linear infinite; } div#foreground{ background: url("https://i.postimg.cc/z3jZZD1B/foreground.png"); z-index: -2; -webkit-animation: cc 253s linear infinite; -o-animation: cc 253s linear infinite; -moz-animation: cc 253s linear infinite; animation: cc 253s linear infinite; } div#top{ background: url("https://i.postimg.cc/PP5GtGtM/midground.png"); z-index: -4; -webkit-animation: da 200s linear infinite; -o-animation: da 200s linear infinite; animation: da 200s linear infinite; } @-webkit-keyframes cc { from{ background-position: 0 0; transform: translateY(10px); } to{ background-position: 600% 0; } } @-o-keyframes cc { from{ background-position: 0 0; transform: translateY(10px); } to{ background-position: 600% 0; } } @-moz-keyframes cc { from{ background-position: 0 0; transform: translateY(10px); } to{ background-position: 600% 0; } } @keyframes cc { 0%{ background-position: 0 0; } 100%{ background-position: 600% 0; } } @keyframes da { 0%{ background-position: 0 0; } 100%{ background-position: 0 600%; } } @-webkit-keyframes da { 0%{ background-position: 0 0; } 100%{ background-position: 0 600%; } } @-moz-keyframes da { 0%{ background-position: 0 0; } 100%{ background-position: 0 600%; } } @-ms-keyframes da { 0%{ background-position: 0 0; } 100%{ background-position: 0 600%; } }