zoukankan      html  css  js  c++  java
  • volatile的原理和实现机制

    JMM-java内存模型:

      简介:程序在运行过程中,会将运算需要的数据从主存复制一份到CPU的高速缓存当中,那么CPU进行计算时就可以直接从它的高速缓存读取数据和向其中写入数据,当运算结束之后,再将高速缓存中的数据刷新到主存当中。

      问题:在多核CPU中,每条线程可能运行于不同的CPU中,因此每个线程运行时有自己的高速缓存(对单核CPU来说,其实也会出现这种问题,只不过是以线程调度的形式来分别执行的),如果一个变量在多个CPU中都存在缓存(一般在多线程编程时才会出现),那么就可能存在缓存不一致的问题。

    为了解决缓存不一致性问题,通常来说有以下2种解决方法:

      1)通过在总线加LOCK#锁的方式

      2)通过缓存一致性协议

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

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

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

    volatile的原理和实现机制

      下面这段话摘自《深入理解Java虚拟机》:

      “观察加入volatile关键字和没有加入volatile关键字时所生成的汇编代码发现,加入volatile关键字时,会多出一个lock前缀指令”

      lock前缀指令实际上相当于一个内存屏障(也成内存栅栏),内存屏障会提供3个功能:

      1)它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成;

      2)它会强制将对缓存的修改操作立即写入主存;

      3)如果是写操作,它会导致其他CPU中对应的缓存行无效。

    参考:

    https://www.cnblogs.com/dolphin0520/p/3920373.html

  • 相关阅读:
    face-morpher过程函数分析
    python,在路径中引用变量的方法
    【django学习】request.POST与request.POST.get两者主要区别
    微信小程序wx.uploadFile的两个坑
    python PIL/cv2/base64相互转换
    OpenCV-Python cv2.imdecode()和cv2.imencode() 图片解码和编码
    cv2.imread()
    详解Ubuntu Server下启动/停止/重启MySQL数据库的三种方式(ubuntu 16.04)
    python使用post请求发送图片并接受图片
    前端 img标签显示 base64格式的 图片
  • 原文地址:https://www.cnblogs.com/chinano1/p/9986132.html
Copyright © 2011-2022 走看看