内存管理_缓存一致性

  计算机在执行程序时,每条指令都是在CPU中执行的,而执行指令过程中,涉及到数据的读取和写入。由于程序运行过程中的临时数据是存放在SRAM(物理内存)当中的,由于CPU执行速度很快,而从内存读取数 据和向内存写入数据的过程跟CPU执行指令的速度比起来要慢的多,因此如果任何时候对数据的操作都要通过和内存的交互来进行,会大大降低指令执行的速度,因此在CPU里面就有了一级、二级Cache(DRAM)。也就是,当程序在运行过程中,会将运算需要的数据从RAM复制一份到Cache中,那么CPU进行计算时就可以直接从它的Cache读数据和向其写入数据,当运算结束之后,再将Cache中的数据刷新到物理内存当中。对于一个运算:i++;

  当线程执行这个语句时,会先从主存当中读取i的值,然后复制一份到高速缓存当中,然后CPU执行指令对i进行加1操作,然后将数据写入高速缓存,最后将高速缓存中i最新的值刷新到主存当中。这个代码在单线程中运行是没有任何问题的,但是在多线程中运行就会有问题了。在多核CPU中,每条线程可能运行于不同的CPU中,因此每个线程 运行时有自己的高速缓存(对单核CPU来说,其实也会出现这种问题,只不过是以线程调度的形式来分别执行的)。比如同时有2个线程执行这段代码,假如初始时i的值为0,那么我们希望两个线程执行完之后i的值变为2,但最后的结果有可能是1。

   这就是著名的缓存一致性问题。通常称这种被多个线程访问的变量为共享变量。

  也就是说,如果一个变量在多个CPU中都存在缓存(一般在多线程编程时才会出现),那么就可能存在缓存不一致的问题。

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

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

  2)通过缓存一致性协议

  这2种方式都是硬件层面上提供的方式。

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

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

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

时间: 2024-10-11 21:22:15

内存管理_缓存一致性的相关文章

Unity游戏开发中的内存管理_资料

内存是手游的硬伤——Unity游戏Mono内存管理及泄漏http://wetest.qq.com/lab/view/135.html 深入浅出再谈Unity内存泄漏http://wetest.qq.com/lab/view/150.html 这一次,我优化了37%的内存http://wetest.qq.com/lab/view/147.html Unity项目资源加载与管理http://wetest.qq.com/lab/view/124.html Android应用内存泄露分析.改善经验总结h

内存管理_深入剖析volatile关键字

四.深入剖析volatile关键字 在前面讲述了很多东西,其实都是为讲述volatile关键字作铺垫,那么接下来我们就进入主题. 1.volatile关键字的两层语义 一旦一个共享变量(类的成员变量.类的静态成员变量)被volatile修饰之后,那么就具备了两层语义: 1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的. 2)禁止进行指令重排序. 先看一段代码,假如线程1先执行,线程2后执行: //线程1 boolean stop =

内存管理_原子性、可见性、有序性

原子性:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行 比如存取款操作,存款和取款操作必须全部完成,或者全部不完成. 可见性:指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值. eg: //Thread 1 int i = 0; i = 10; //Thread 2 j = i; 假若执行Thread1的是CPU0,执行Thread2的是CPU1.由上面的分析可知,当Thread1执行 i =10这句时,会先把i的初始

操作系统(5)_内存管理_李善平ppt

i386先通过段是管理,在通过页是管理

LDD读书笔记_内存管理

本部分不仅仅是LDD的介绍部分, 还包括了对linux的内存模型的总结. 一句话总结 伙伴系统是基石, slab基于伙伴系统, kmalloc基于slab. 要点 ?伙伴系统是对连续大内存而言, 得到的内存的单位从1个page到211 page, 解决外部碎片问题. ?Slab分配器是针对小内存而言, 从32B到128KB, 解决的是内部碎片问题, kmalloc是基于slab分配器的. ?如果物理内存加上需要映射的IO空间内存的大小加起来超过896M, 则有必要开启highmen的功能. Ag

操作系统中作业、线程、进程、内存管理、垃圾回收以及缓存等概念

作业:用户在一次解题或是一个事务处理过程中要求计算机系统所做的工作的集合.它包括用户程序.所需要处理的数据以及控制命令等.作业是由一系列有序的步骤组成. 进程:一个程序在一个数据集合的一次运行过程.所以一个程序在不同数据集合上运行,乃至一个程序在同样的数据集合上的多次运行都是不同的进程. 线程:线程是进程中的一个实体,被系统独立调度和执行的基本单位. 管程:管程实际上是定义了一个数据结构和在该数据结构上的能为并发进程做执行的一组操作,这组操作能同步进程和改变管程中的数据. 操作系统中作业.线程.

黑 马 程 序 员_视频学习总结<Objective-C>----04 内存管理、protocol、block、ARC

---------------------- ASP.Net+Unity开发..Net培训.期待与您交流! ---------------------- 一.内存管理 1.为什么要用内存管理: 移动设备的内存极其有限,每个app所能占用的内存是有限制的.当app所占用的内存较多时,系统会发出内存警告,这时得回收一些不需要再使用的内存空间.比如回收一些不需要使用的对象.变量等 2.管理范围: 任何继承了NSObject的对象,对其他基本数据类型(int.char.float.double.stru

Java千百问_07JVM架构(005)_显示内存管理有什么弊端

点击进入_更多_Java千百问 1.显示内存管理有什么弊端 手动内存管理一般被称为显示内存管理,显示内存管理经常发生两种情况: 引用悬挂 当一个被某个引用变量正在使用的内存空间,在重新分配过程中被释放掉了,释放后,该引用变量就处于悬挂状态(所引用的对象已经不存在了). 如果这个被悬挂引用变量,试图操作原来对象的时候,由于该对象本身的内存空间已经被手动释放掉了(已经不存在了),所以这个执行结果是不可预知的. 内存泄漏 当某些引用变量不再引用该内存对象的时候,而该对象原本占用的内存并没有被释放,这种

深入浅出处理器(下)_内存管理(映射)

专题1-深入浅出处理器 处理器(下)_内存管理(映射) 1.内存管理单元(MMU) 内存管理单元简称MMU,它负责虚拟地址到物理地址的映射,并提供硬件机制的内存访问权限检查.MMU使得每个用户进程拥有自己独立的地址空间,并通过内存访问权限的检查保护每个进程所用的内存不被其他进程破坏.操作系统系统内存管理单元实现虚拟内存和内存保护.重点就在于地址映射:页表的结构与建立.映射的过程. 2.问题:下面程序输出结果是否完全相同? int g_v = 1; int main(void) { printf(