系列文章目录
多核cpu怎么保证数据一致性(一)为什么要做指令重排序?
多核cpu怎么保证数据一致性(二)cpu为什么要用高速缓存?L1,L2,L3 cache
多核cpu怎么保证数据一致性(三)MESI缓存一致性协议
多核cpu怎么保证数据一致性(四)volatile关键字、happens-before原则、内存屏障
前言
上篇文章《多核cpu怎么保证数据一致性(一)为什么要做指令重排序?》,我们说了为什么要做指令重排序,以及重排序保证指令正确执行的原则,本篇我们就从cpu的结构说说多核cpu怎么保证数据一致性的
一、cpu存取数的内存结构
我们知道cpu分为三级缓存和内存,如下图(图1-1)
其中l1cache,l2cache,l3cache(其中l1cache中又分为L1D(L1 Data Cahce)和L1I(L1 Instruction Cache),我们这里只说数据缓存,指令缓存没什么可讲的哈),L3cache下面就是我们的主存,也是我们说的内存。
其中L1和L2cache是每个cpu核独享的,L3cache是多个cpu核共享的。
二、CPU为什么要有那么多级的缓存呢?
我用的是macbook pro 2017款,这是我的电脑配置:
可以看到我的处理器是2.8GHz,这是一个什么概念呢,就是每秒钟可以产生2.8G个(0或1)这样的数字,我们知道计算机中的程序和数据都是0和1组成的,这就是cpu的运算效率。一个int类型由32个bit组成,也就是说我处理一个int类型只要10ns,而我们从内存中读取一次数据呢,需要1000ns,差了100倍(这个速度相当于一个是高铁的速度,一个是步履蹒跚的老太太走路,差距巨大)。
虽然我的内存有16G,但是对于cpu来说去内存读数据还是太慢了。我们为了提升cpu存取数据的效率,如果能把cpu读取数据的效率控制在30-40ns,那cpu的效率将显著提升,此时就诞生了我们的cpu高速缓存。
为什么高速缓存要分为三级呢?这是跟硬件有关的,为了提升cpu存取数据的效率,那么这些数据一定要距离cpu足够的近,此时高速缓存的空间就很有限了,所以l1cache是距离cpu最近的,当然空间也是最小的,距离图示如下:
三、cpu为什么要用多核?
其实一个cpu的内核,性能是有极限的(上面说的2.8GHz),为了提升性能,让计算机做更多的任务,所以就要使用多个内核来提升效率。关于多核里面的高速
四、cpu怎么处理多核中的高速缓存数据不一致
我们在图1-1中说到,l1cache和l2cache是cpu的核独有的(如我的电脑4核16G,每个cpu核中都有l1cache和l2cache),如果遇到多线程的情况,如下代码所示:
public class VolatileTest {
private static volatile int COUNTER = 0;
public static void main(String[] args) {
new ChangeListener().start();
new ChangeMaker().start();
}
static class ChangeListener extends Thread {
@Override
public void run() {
int threadValue = COUNTER;
while ( threadValue < 5){
if( threadValue!= COUNTER){
System.out.println("Got Change for COUNTER : " + COUNTER + "");
threadValue= COUNTER;
}
}
}
}
static class ChangeMaker extends Thread{
@Override
public void run() {
int threadValue = COUNTER;
while (COUNTER <5){
System.out.println("Incrementing COUNTER to : " + (threadValue+1) + "");
COUNTER = ++threadValue;
try {
Thread.sleep(500);
} catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
}
我的数据既有在线程ChangeListener中执行,又有在线程ChangeMaker中执行,但是两个线程都用到了COUNTER这个共享变量(此时可能ChangeListener在核1上执行,ChangeMaker在核2上执行)。但是我存取数据都是在缓存中的,而缓存是cpu核独有的,怎么保证每个cpu核读到的数据都是最新的且正确的呢,我们将在下一章节说说“cpu的MESI缓存一致性协议”
总结
今天我们说了
- cpu为什么要用多核:以为单个cpu核的性能是有极限的
- cpu为什么要用高速缓存:从内存中存取数据太慢
下一章节,我们将说说cpu怎么保证缓存的一致性:MESI缓存一致性协议
其实我一直认为,工欲善其事,必先利其器,在工具的使用上,我准备了专栏《java开发工具》,如果你感兴趣可以来看看