计算机底层原理

文章目录

  • 1、计算机组成
  • 2、存储器的层次结构
  • 3、cache line 的概念 缓存行对齐 伪共享
  • 4、CPU乱序执行的概念
    • 4.1 一道面试题:DCL(Double Check Lock双重检查锁)单例模式要不要加volatile
    • 4.2 合并写技术
  • 5、程序运行的底层原理
  • 6、锁
    • 6.1 锁的概念
    • 6.2 synchronized关键字
      • 6.2.1 自旋锁的核心——CAS(compareAndSwap )
      • 6.2.2 偏向锁

1、计算机组成



CPU = ALU + PC + Registers + cache

  • ALU ——> 运算单元/算数逻辑单元
    • 计算寄存器的数据,然后写回到内存
  • PC(program counter) ——> 指令寄存器 /程序计数器
    • 存放下一条指令的地址
  • Register ——> 寄存器
    • 在PC找到指令的地址,读进指令后,发现该指令需要数据,将数据放到寄存器(registers)
  • cache ——>缓存(redis)

CPU通过总线内存读数据

2、存储器的层次结构



从L0到L4,速度大概相差100倍
计算机底层原理_第1张图片
计算机底层原理_第2张图片

  • 多核CPU
    • 一个GPU中存在多个核,每个核中包含1级、2级缓存。所有核共享3级缓存。
    • 在进行数据查找时,查找顺序为L1、L2、 L3.
  • 超线程
    • 一个运算单元,两组线程对应的资源单元(核中包含两组PC、两组寄存器),来提高效率。
    • 四核八线程:就是有4 个ALU,每个和里有两组寄存器和PC

3、cache line 的概念 缓存行对齐 伪共享


  • 计算机通过内存总线从内存读数据,是一块一块的读取的,每一块叫cache line
    • 英特尔的CPU,一个cache line 也就是一个缓存行是64个字节(bite)
  • 当ALU计算需要数据时(比如是数据x),依次在L1、L2、L3中寻找, 没有就会去内存读取,将“x,y"这一缓存行同时读进来,这时,当ALU处理完数据x后,需要y时,发现y和x被同时读进内核了,这时的运算速度会大大提升
    计算机底层原理_第3张图片
  • 这时存在一个问题,缓存保持一致
    • 针对两个线程使用同一缓存行的数据,一个在使用其中的x, 一个在使用y,如果其中一个对x进行了更改,要求另一个线程必须可见,通知另一个线程可见的这种操作就叫 缓存一致性协议,保证缓存行的数据在不同线程中保持一致.
      计算机底层原理_第4张图片
  • 缓存行的4中状态MESI:
    • Modified:被修改
    • Exclusive:独享
    • Shared:分享,只读不写
    • Invalid:失效

这时的一个流程就是,当一个线程中的x被修改,此时该缓存行的状态会被更改为Modified,内核会通过缓存锁去告知另一个线程,他的缓存行Invalid,它需要从内存中重新读取。

4、CPU乱序执行的概念


计算机底层原理_第5张图片
比如在多核CPU同时运行时,是不允许乱序执行的,这时Java使用volatile来实现不允许乱序执行

  • volatile的核心两点:
    • 线程之间的可见性
    • 禁止CPU的乱序执行
  • cpu的乱序执行
    • 在JVM层级是要通过内存屏障来实现,来防止它乱序执行
    • 到虚拟机这个层级、C++这个层级,实际上是通过一条汇编指令,通过lock这条指令来完成的

4.1 一道面试题:DCL(Double Check Lock双重检查锁)单例模式要不要加volatile

-计算机底层原理_第6张图片
先判断INSTANCE是否为空,然后上锁,然后再次检查INSTANCE是否为空,这是为了防止该线程在上锁期间其他线程执行了INSTANCE = new Mgr06()
- DCL(Double Check Lock双重检查锁)单例模式要加volatile
计算机底层原理_第7张图片

  • 对象的创建过程

    • 0 new #2 //在内存中申请一个对象,分配了一块内存,内存中的m为初始值0。
    • 4 invokespecial #3 //执行该句后,m被赋值为8。
    • astore_1 //执行该句后 t 和 才会和真正的对象建立关联。
      计算机底层原理_第8张图片
  • 若不使用volatile进行禁止指令重排序,则在DCL单例new对象时,发生指令乱序,先使变量和内存建立连接,然后没等进行下一步的初始化时,下面的程序就进行了变量是否为null的判断,并使用这个半初始化状态的对象继续向下执行,导致程序出现错误。
    内存屏障

  • JVM级内存屏障:
    计算机底层原理_第9张图片

    • JSR内存屏障
      • LoadLoad屏障:
      • StoreStore屏障:
      • LoadStore屏障:
      • StoreLoad屏障:
  • 硬件级内存屏障:

4.2 合并写技术

  • 计算单元AUL和L1缓存中间还有一个缓存,叫WC_buffer(WriteCombing, 合并写),它只有4个字节。
  • 合并写:当CPU需要写回一个值到内存或缓存时,内存会首先把这些值存在WC_buffer中,这个缓存四字节满了之后,一次性把这四个字节写到L1中。

5、程序运行的底层原理


  • 程序:qq.exe, PowerPoint.exe
  • 进程:资源分配的基本单位。(程序启动、进入内存。比如,双击qq.exe,这时就会将磁盘中的数据(指令和代码)传给内存,)
  • 线程:程序执行的基本单位(从main线程开始执行)
  • 程序如何开始运行
    • CPU读指令 PC,读数据 Register, 计算 ALU ,回写,-> 下一条
  • 线程如何进行调度
    • 线程调度器(操作系统、OS)
  • 线程切换的概念
    • Context Switch CPU保存现场 ,执行新线程,恢复现场,继续执行原线程这样的一个过程
      用户级线程(JVM线程)和操作系统级线程(也就是内核级线程)
  • 一个JVM线程对应一个内核级线程 1:1
  • go语言中叫协程,它和内核级线程是m:n的关系,且m远远大于n

6、锁


6.1 锁的概念

  • 锁的概念:对线程上锁就是,只有等这个线程执行结束,别的线程才能执行
  • 不持有锁的线程怎么办:忙等待(自旋锁,也叫轻量级锁),等待队列(需要经过操作系统调度,也叫重量级锁)
    • 自旋锁一定比重量级锁的效率高吗?不是,当线程执行时间长,且线程多时,选择重量级锁,等待系统的调度

6.2 synchronized关键字

synchronized从重量级锁到自旋锁到现在更加复杂的锁

6.2.1 自旋锁的核心——CAS(compareAndSwap )

  • 在进行m++时,从内存读取数m给ALU,然后在往回写入时判断,要往回写入的数和内存中的数是否一样,如果不一样,将其存入,一直运行到两个数相同
    计算机底层原理_第10张图片
  • 存在的两个问题:(针对多核cpu,单核不存在这个问题)
    • ABA问题: (我们将内存的0送入ALU计算为1,现在将1重新写入内存,这时进行判断,内存是0与1不等。在判断时存在一个问题,判断时的0是读进ALU的0么,这个0可能是经历了其他线程变成8后又变为0,这就是ABA问题)
      • 解决方法:为其加个版本号(也就是为内存0加个版本号)
    • CAS修改值时候的原子性问题:(我们将内存的0送入ALU计算为1,现在将1重新写入内存,这时进行判断内存0还是0,这是将内存0赋值为1。但是现在出现一个问题就是,在判断0是0后,0变1之前,内存0被另外一个线程赋值为8了,这时候怎么办),这时候需要保证他是原子性的,怎么保证的呢?
      • lock cmpxchg 指令 //汇编指令 CPU采用CAS的方式去访问内存的指令
        • lock 是用来锁总线, 来保证cmpxchg的原子性

6.2.2 偏向锁

计算机底层原理_第11张图片

  • 偏向锁的概念:
    • 偏向锁不是锁。是第一个线程过来,不用启动锁竞争,就能使用,但是只要有其他资源过来竞争,就要进行锁升级
    • 他是为了那些在百分之七八十的时间,只有一个线程在运行synchronized的代码所设计的一把锁
    • 如果没有偏向锁,每次即使只过来一个线程也要启动锁竞争,过于浪费时间。
    • 深入理解Java锁升级:无锁 → 偏向锁 → 轻量级锁 → 重量级锁 https://blog.csdn.net/qq_40722827/article/details/105598682
  • JOL(Java Object Layout, Java 对象布局)
    • Object o = new Object()
      • new一个新对象它占16个字节:
        • markword(8个字节)
        • classpointer(4个字节):new出来的对象属于哪一个类的,也可以认为他是只想object.class的指针
        • 后面4个字节是,存放成员变量,如果没有,留着对齐(对齐:如果不能被8整除,就变成能被8整除)

你可能感兴趣的:(计算机底层知识,java,后端,系统安全)