12.4 计算机组成、MESI协议、名词解释

1.计算机组成

12.4 计算机组成、MESI协议、名词解释_第1张图片
计算器组成.png

2.多核CPU:一个CPU中有多个核心

12.4 计算机组成、MESI协议、名词解释_第2张图片
一个双核CPU.png

3.缓存行 Cache line伪共享

  • 缓存是为了降低CPU和主存速度差异,采用的解决办法。
  • 每个缓存里面都是由缓存行组成的,缓存系统中是以缓存行(cache line)为单位存储的,常见的缓存行大小为64个字节
  • 当多线程修改互相独立的变量时,如果这些变量共享同一个缓存行,就会无意中影响彼此的性能,这就是伪共享(PS:采用缓存行对齐来解决伪共享问题)
    12.4 计算机组成、MESI协议、名词解释_第3张图片
    缓存行伪共享.png

      在core1上运行的线程修改变量X,同时core2上的线程修改变量Y。不幸的是,这两个变量在同一个缓存行中。每个线程都要去竞争缓存行的所有权来修改变量。如果core1获得了所有权,缓存子系统将会使core2中对应的缓存行失效。这样来来回回读取主存数据,大大影响了性能。如果互相竞争的核心位于不同的插槽,就要额外横跨插槽连接
public class Test_CacheLine{
    //使用缓存行对齐来解决伪共享
    private static class Padding{
        public long p1,p2,p3,p4,p5,p6,p7;
    }
    
    private static class T /**extends Padding**/{
        public volatile long x = 0L;
    }
    //使对象在同一个缓存行
    public static T[] arr = new T[2];
    
    static {
        arr[0] = new T();
        arr[1] = new T();
    }
    
    public static void main(String[] args) throws Exception{
        Thread t1 = new Thread(() ->{
            for(long i=0; i<1000_0000L; i++){
                arr[0].x = i;
            }
        });
        
        Thread t2 = new Thread(() ->{
            for(long i=0; i<1000_0000L; i++){
                arr[1].x = i;
            }
        });
        
        final long start = System.nanoTime();
        t1.start();
        t2.start();
        
        t1.join();
        t2.join();
        System.out.println((System.nanoTime() - start)/100_10000);
    }
}

参考链接:https://www.jianshu.com/p/e338b550850f

4.MESI 协议(X86):让多核 CPU 的高速缓存保持一致

  • M: 代表已修改(Modified)
  • E: 代表独占(Exclusive)
  • S: 代表共享(Shared)
  • I: 代表已失效(Invalidated)
    PS: 缓存锁实现之一,有些无法被缓存的数据或者跨越多个缓存行的数据,必须使用总线锁。

  要解决缓存一致性问题,首先解决核心之间的数据传播, 最常见的一种解决方案就是采用总线嗅探,这个策略,本质上就是把所有的读写请求都通过总线(Bus)广播给所有的 CPU 核心,然后让各个核心去 “嗅探” 这些请求,再根据自己的情况进行响应。
  MESI 协议,是一种叫作写失效(Write Invalidate)的协议。在写失效协议里,只有一个 CPU 核心负责写入数据,其他的核心,只是同步读取到这个写入。在这个 CPU 核心写入 Cache 之后,它会去广播一个 “失效” 请求告诉所有其他的 CPU 核心。其他的 CPU 核心,只是去判断自己是否也有一个 “失效” 版本的Cache line,然后将状态修改成失效状态
  相对于写失效协议,还有一种叫作写广播(Write Broadcast)的协议。在那个协议里,一个写入请求广播到所有的 CPU 核心,同时更新各个核心里的 Cache

12.4 计算机组成、MESI协议、名词解释_第4张图片
写失效.png

12.4 计算机组成、MESI协议、名词解释_第5张图片
写广播.png

参考链接:https://blog.csdn.net/qyf__123/article/details/100904595

5.线程和进程的概念

  • 线程是CPU执行的基本单位
  • 进程是CPU资源分配的基本单位

8.问题

  • 8.1 一个单核CPU+多线程情况下,变量虽然保证了可见性(使用同样的缓存行),但是仍然会出现并发问题。
int i = 1;
if(i == 1){ //B线程进入判断,i仍然是1,执行后续代码
   i++; //A线程准备执行该条指令时,进行了线程切换,即B线程执行
  System.out.println(i);
}
多线程下,打印了多次i值,即出现了并发问题。
  • 8.2 cpu线程数和java线程数有直接关系吗?
    操作系统线程(CPU线程)其实是操作系统利用CPU的中断去切换执行的指令片段模拟出来。
    没有直接关系,正如上面所说,cpu采用分片机制执行线程,给每个线程划分很小的时间颗粒去执行,但是真正的项目中,一个程序要做很多的的操作,
读写磁盘、数据逻辑处理、出于业务需求必要的休眠等等操作,当程序在进行I/O操作的时候,线程是阻塞的,线程由运行状态切换到等待状态,此时
cpu会做上下文切换,以便处理其他的程序;当I/O操作完成后,cpu 会收到一个来自硬盘的中断信号,并进入中断处理例程,手头正在执行的线程因此被
打断,回到 ready 队列。而先前因 I/O 而waiting 的线程随着 I/O 的完成也再次回到就绪队列,这时 cpu 可能会选择它来执行。
(PS:摘抄于网络)

你可能感兴趣的:(12.4 计算机组成、MESI协议、名词解释)