内存模型一:什么是内存模型

纵然工作再忙也应该要留下自己思考的时间,这次我总结了一下对于内存模型的理解,起因是在公司听了一场关于多线程编程的分享会。首先解释一下,内存模型和对象模型是不同的。对象模型说的是一个对象是如何被设计的,其在内存中是如何布局的。而内存模型说的是,在多核多线程环境下,各种不同的CPU是如何以一种统一的方式来与内存交互的。

背景知识:CPU的高速缓存

总所周知,CPU和内存并不是直接交换数据的,它们之间还隔着一个高速缓存。高速缓存是对程序员透明的,这意味在编程的时候是感知不到CPU的缓存的存在的。一般情况下确实如此,但在,在某些特殊的情形下(多核多线程),就不能忽略缓存的存在了。这其实是和缓存的设计有关系,一般多处理器下的每个CPU都有一个自己的缓存,存储在这个缓存的数据是其它CPU是无法查看的。

引入问题1:内存可见性

问题来了,由于缓存是每个CPU私有的,那么在多线程环境下,某个CPU修改了变量x后保存在本地缓存,对于其它CPU,何时才能发现变量x被修改呢?如何保证其它CPU的缓存中持有的x的值是最新的呢?

由此可见,在多核多线程环境下,读写共享变量要解决的不仅是原子性,还需要保证其内存可见性。更糟的是,现代CPU通常在执行指令时会允许一定程度上的乱序,这使保证在多个CPU缓存的数据一致更是增加了复杂性。通常方法是通过一个协议来保证数据在各个CPU的缓存是一致性,这就是缓存一致性协议。

关于缓存一致性简单的举个列子。CPU-0尝试STORE(更新)变量x,但其发现其它CPU的缓存也持有这个x的copy(x此时为Shared状态,非单个CPU独占),那么当CPU-0在STORE之前,必须通过一个disable消息,告诉其它CPU所持有的变量x已经为脏数据,是不可用状态。其它CPU在收到这个disable消息后必须回应CPU-0一个ack消息,这时候CPU-0才能开始STORE变量x。

通过缓存一致性协议之后,内存可见性问题似乎是得以解决了。但是,这里面还隐藏着另外一个问题:指令乱序!

引入问题2:乱序(memory reorder)

先来解释一下,乱序,指的是程序指令实际上执行的顺序,和我们书写的指令的顺序不一致。乱序分两种,分别是编译器的指令重排和CPU的乱序执行。本意上乱序是为了优化指令执行的速度而产生的。并且为了维护程序原来的语义,编译器和CPU不会对两个有数据依赖的指令重排(reorder)。这种保护在单线程的环境下是可以工作的,但是到了多线程,问题就复杂了。

举个例子,CPU-0将要执行两条指令,分别是:

  1. STORE x
  2. LOAD y

当CPU-0执行指令1的时候,发现这个变量x的当前状态为Shared,这意味着其它CPU也持有了x,因此根据缓存一致性协议,CPU-0在修改x之前必须通知其它CPU,直到收到来自其它CPU的ack才会执行真正的修改x。但是,事情没有这么简单。现代CPU缓存通常都有一个Store Buffer,其存在的目的是,先将要Store的变量记下来,注意此时并不真的执行Store操作,然后待时机合适的时候再执行实际的Store。有了这个Store Buffer,CPU-0在向其它CPU发出disable消息之后并不是干等着,而是转而执行指令2(由于指令1和指令2在CPU-0看来并不存在数据依赖)。这样做效率是有了,但是也带来了问题。虽然我们在写程序的时候,是先STORE x再执行LOAD y,但是实际上CPU却是先LOAD y再STORE x,这个便是CPU乱序执行(reorder)的一种情况!

当你的程序要求指令1、2有逻辑上的先后顺序时,CPU这样的优化就是有问题的。但是,CPU并不知道指令之间蕴含着什么样的逻辑顺序,在你告诉它之前,它只是假设指令之间都没有逻辑关联,并且尽最大的努力优化执行速度。因此我们需要一种机制能告诉CPU:这段指令执行的顺序是不可被重排的!做这种事的就是内存屏障(memory barrier)!

内存屏障

还是上面那个例子,如果不想指令1、2被CPU重排,程序应该这么写:

  1. STORE x
  2. WMB (Write memory barrier)
  3. LOAD y

通过在STORE x之后加上这个写内存屏障,就能保证在之后LOAD y指令不会被重排到STORE x之前了。

内存模型是什么

前面讲了那么多,那么内存模型是什么呢?

首先,残酷的现实就是每个CPU设计都是不同的,每个CPU对指令乱序的程度也是不一样的。比较保守的如x86仅会对Store Load乱序,但是一些优化激进的CPU(PS的Power)会允许更多情况的乱序产生。如果目标是写一个跨平台多线程的程序,那么势必要了解每一个CPU的细节,来插入确切的、足够的内存屏障来保证程序的正确性。这是多么的不科学啊!科学的做法应该是,我为一个抽象的机器写一套抽象的程序,然后在不同的平台下让编程语言、编译器来生成合适的内存屏障。因此,我们有了内存模型的概念。不同平台下的实现差别被统一的内存模型所隐藏,只需要根据这个抽象的内存模型来编写程序即可,这便是伟大的抽象...

因此,在C++11里有了内存模型的在之后,我们可以仅通过标准库就实现出跨平台线程安全的lock free程序(这在C++11之前是做不到的,虽然Java早就有了内存模型)。

内存模型 C++ 和Java内存模型相关推荐

  1. JVM之深入理解JVM内存结构(Java内存结构/Java内存区域)、Java内存模型

    Java作为一种面向对象的,跨平台语言,其对象.内存等一直是比较难的知识点.而且很多概念的名称看起来又那么相似,很多人会傻傻分不清楚.比如本文我们要讨论的JVM内存结构.JAVA内存结构.JAVA内存 ...

  2. Java内存管理:深入Java内存区域

    Java内存管理:深入Java内存区域 本文引用自:深入理解Java虚拟机的第2章内容 Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 概述 ...

  3. java内存图解_图解JAVA内存模型(JMM:JAVA Memory Model)

    本文主要说明两个问题:JMM存在的意义是什么?JMM内部的工作原理是什么(重点讲一下并发编程模式下的数据访问一致性问题) . 1.为什么要使用JMM? 当我们刚开始接触JAVA语言的时候,就会被告知J ...

  4. java内存数据被篡改,初涉Java内存模型

    Java内存模型 Java实现会带来不同的"翻译",不同CPU平台的机器指令又千差万别,无法保证并发安全的效果一致. JVM内存结构 VS Java内存模型 VS Java对象模型 ...

  5. java内存模型 final_聊聊Java内存模型

    一.Java内存模型 硬件处理 电脑硬件,我们知道有用于计算的cpu.辅助运算的内存.以及硬盘还有进行数据传输的数据总线.在程序执行中很多都是内存计算,cpu为了更快的进行计算会有高速缓存,最后同步至 ...

  6. JVM内存管理:深入Java内存区域与OOM

    Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 概述: 对于从事C.C++程序开发的开发人员来说,在内存管理领域,他们即是拥有最高权力的皇帝 ...

  7. java多线程模型_1、java线程模型

    要了解多线程,先需要把java线程模型搞清楚,否则有时候很难理清楚一个问题. 硬件多线程: 物理机硬件的并发问题跟jvm中的情况有不少相似之处,物理机的并发处理方案对于虚拟机也有相当大的参考意义.在买 ...

  8. 32位jdk最大内存_你了解Java 内存区域和GC机制吗?

    目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...

  9. java 二维数组内存溢出_模拟Java内存溢出

    本文通过修改虚拟机启动参数,来剖析常见的java内存溢出异常(基于jdk1.8). 修改虚拟机启动参数 这里我们使用的是IDEA集成开发环境,选择Run/Debug Configurations 然后 ...

  10. jstat 内存泄漏_基于Java内存dump文件分析解决内存泄漏问题

    概述 本文介绍一次解决现场java内存泄漏问题的经过,希望能提供后续遇到类似情况的读者一点思路. 生产环境发现的问题问题 生产环境运维人员反馈,服务器(windows系统)卡死,相关的服务都运行异常, ...

最新文章

  1. Career Service, what skills do you need for career domain?
  2. word排版案例报告_停工不停学丨项目部开展Word办公软件使用技能培训
  3. 错误 找不到或无法加载主类
  4. xcode8 崩溃问题
  5. 第21条:用函数对象表示策略
  6. React Native实例之房产搜索APP
  7. java for语句
  8. everthing 和 wox查找文件 文件夹 快速入门例子
  9. android 模拟内存不足,雷电模拟器内存不足怎么办?雷电安卓模拟器怎么修改内存大小?...
  10. shell美元符_Linux Shell中的美元符号$ | 学步园
  11. Oracle EBS AutoConfig详解
  12. idea自动去除导入但未使用的包
  13. 解决:syntax error at line xxx: `<<‘ unmatched
  14. python笔记-05(条件、循环及其他语句)
  15. Painter下载Painter中文版下载 Substance 3D Painter最新下载和安装
  16. 电子招投标须知的重要过程
  17. WORD2010/WPS使用快捷键
  18. 组策略9-禁用命令行CMD
  19. lync2013之边缘服务器的部署
  20. Winclone Pro 7 for mac(分区备份还原工具)汉化版

热门文章

  1. HDU4279(2012年天津网络赛---数论分析题)
  2. 31.错误处理.rs
  3. Shell特殊变量:Shell $0, $#, $*, $@, $?, $$和命令行参数
  4. 2_7 FlyweightMode 享元模式
  5. C++ 泛型编程(一):模板基础:函数模板,类模板,模板原理,模板匹配规则
  6. 腾讯云+FFmpeg打造一条完备高效的视频产品链
  7. ffmpeg解封装及解码实战
  8. Hadoop之Hadoop序列化
  9. 流量洪峰成为常态,腾讯数据库如何高性能支撑海量SQL查询?
  10. curl模拟delete/put/post/get请求