要解决的问题

在硬件环境下,基于高速缓存的存储交互很好的解决了处理器与内存的速度之间的矛盾,但同时也带给计算机系统带来了复杂的缓存一致性问题。简单点说,在多处理器系统中,每个处理器都有自己的高速缓存,他们共享主内存,当在某个时刻,多个处理器的运算任务都涉及同一块内存区域,很有可能各自缓存中的运算结果不一致,此时若要执行将高速缓存中的数据同步回主内存的操作,那么问题就来了:系统以哪个缓存的数据为准? 由此便出现了解决缓存一致性的协议、规范。“内存模型”一词即指在特定的操作协议下,对特定的内存和高速缓存进行读写访问的过程抽象,不同架构的物理机器可以拥有自己的内存模型。JVM 也实现了这样的一套规范模型。

并发编程模型的分类

在并发编程中,需要解决的两个关键问题分别是:线程之间如何通信(以何种机制来交换信息)以及线程之间如何同步(不同线程之间操作发生的相对顺序机制)。

线程之间的通信机制有两种:共享内存和消息传递。在共享内存的并发模型里,线程之间共享程序的的公共状态,线程之间通过读-写内存中的公共状态来隐式进行通信;在消息传递的并发模型里,线程之间没有公共状态,必须通过明确的发送消息来显示通信。

在共享内存的并发编程模型里,同步就显得至关重要,必须显示指定。Java 的并发采用的就是共享内存模型,不同的线程之间无法访问对方本地内存中的变量,线程间变量值的传递均需要通过主内存来完成。

Java 内存模型的抽象

在 Java 中,所有实例域、静态域和数组元素存储在堆(主内存主要对应了堆中对象实例数据部分)中,堆内存在线程之间共享,因此他们也叫共享变量。而局部变量、方法参数和异常处理器参数是属于线程私有的,不会被共享。每个线程还有自己的工作内存,其中保存了被该线程使用到的变量的主内存副本拷贝,线程对共享变量的所有操作(读取、赋值等)都必须在工作内存中进行,而不能直接读-写主内存中的共享变量。是不是和如上描述的硬件机制非常相似!实际上就是如此:主内存可以看出直接对应于物理硬件的内存,工作内存优先使用的是寄存器和高速缓存,因为程序运行时主要访问的是工作内存。

如上图所示,线程A和线程B通过共享变量实现了隐式通信,同时通过 JMM 控制实现多个线程之间的同步。解决了多核、多线程间数据的共享以及对内存操作的有序性的问题。

内存间交互操作细节

关于主内存与工作内存之间具体的交互协议,即一个变量如何从主内存拷贝到工作内存、又如何从工作内存同步回主内存的实现细节,JMM 中定义了 8 种操作来完成,且在虚拟机实现中都保证以下的每种操作都是原子的、不可再分的。

lock(锁定):作用于主内存的共享变量,把一个共享变量标识为一条线程独占的状态

read(读取):作用于主内存的共享变量,把一个共享变量的值从主内存传输到线程的工作内存的读缓冲区中,以便随后的 load 操作使用

load(载入):作用于工作内存的共享变量,把 read 操作从主内存中读取到读缓冲区中的变量值放入工作内存的共享变量副本中

use(使用):作于于工作内存的共享变量副本,把工作内存中的共享变量副本的值传递给执行引擎

assign(赋值):作用于工作内存的共享变量副本,把一个从执行引擎接收到的值赋给工作内存中的共享变量副本

store(存储):作用于工作内存的共享变量副本,把工作内存中的共享变量副本的值通过写缓冲区传送到主内存中,以便随后的 write 操作使用

write(写入):作用于主内存的共享变量,把 store 操作存储到写缓冲区的值放入主内存的共享变量中

unlock(解锁):作用于主内存的共享变量,把一个处于锁定状态的共享变量释放出来,释放后的变量才可以被其它线程锁定

上述 8 种原子操作还必须满足如下规则:

不允许 read 和 load、store 和 write 操作之一单独出现,即不允许一个变量从主内存读取了但工作内存不接受,或者从工作内存发起了回写但主内存不接受的情况出现。

read、load 和 store、write 此两类操作必须按顺序执行,但并非必须连续执行,也即在 read 和 load、store 和 write 操作之间是可以插入其他指令的

不允许一个线程丢弃它最近的 assign 操作,即变量在工作内存中改变了之后必须把该变化同步回主内存

不允许一个线程无原因地(没有发生任何 assign 操作)把数据从线程的工作内存同步回主内存

一个新的变量只能在主内存中“诞生”,不允许在工作内存中直接使用一个未被初始化(load 或 assign)的变量,即对一个变量实施 use 或 store 操作前必须先执行过 assign 或 load 操作

一个变量在同一时刻只允许一个一条线程对其进行 lock 操作,但 lock 操作可以被同一条线程重复执行多次,多次 lock 执行后,只有执行相同次数的 unlock 操作,变量才会被解锁

如果对一个变量执行 lock 操作,那将会清空工作内存中此变量的值,在执行引擎使用这个变量前,需要重新执行 load 或 assign 操作初始化变量的值

如果一个变量事先没有被 lock 操作锁定,那就不允许对它执行 unlock 操作,也不允许 unlock 一个被其它线程锁定的变量

对一个变量执行 unlock 前必须先把此变量同步回主内存中(执行 store、write 操作)

深入理解 Java 内存模型(一)- 内存模型介绍的更多相关文章

  1. 《深入理解 java 虚拟机》学习 -- 内存分配

    <深入理解 java 虚拟机>学习 -- 内存分配 1. Minor GC 和 Full GC 区别 概念: 新生代 GC(Minor GC):指发生在新生代的垃圾收集动作,因为 Java ...

  2. 深入理解Java虚拟机(一)——JVM内存模型

    文章目录 程序计数器 定义 作用 特点 Java虚拟机栈 定义 特点 本地方法栈 定义 Java堆 定义 特点 方法区 定义 特点 运行常量池 直接内存 总结 Java虚拟机的内存空间分为五个部分: ...

  3. 【深入理解Java虚拟机】自动内存管理机制——垃圾回收机制

      Java与C++之间有一堵有内存动态分配和垃圾收集技术所围成的"高墙",墙外面的人想进去,墙里面的人却想出来.C/C++程序员既拥有每一个对象的所有权,同时也担负着每一个对象生 ...

  4. 【深入理解Java虚拟机】自动内存管理机制——内存区域划分

      Java与C++之间有一堵有内存动态分配和垃圾收集技术所围成的"高墙",墙外面的人想进去,墙里面的人却想出来.C/C++程序员既拥有每一个对象的所有权,同时也担负着每一个对象生 ...

  5. 深入理解Java虚拟机(自动内存管理机制)

    文章首发于公众号:BaronTalk 书籍真的是常读常新,古人说「书读百遍其义自见」还是很有道理的.周志明老师的这本<深入理解 Java 虚拟机>我细读了不下三遍,每一次阅读都有新的收获, ...

  6. 深入理解Java虚拟机之JVM内存布局篇

    内存布局**** ​ JVM内存布局规定了Java在运行过程中内存申请.分配.管理的策略,保证了JVM的稳定高效运行.不同的JVM对于内存的划分方式和管理机制存在部分差异.结合JVM虚拟机规范,一起来 ...

  7. 深入理解JAVA虚拟机原理之内存分配策略(二)

    更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680 1.对象优先在Eden分配 大多情况,对象在新生代Eden区分配.当Eden区没 ...

  8. 《深入理解Java内存模型》读书总结

    概要 文章是<深入理解Java内容模型>读书笔记,该书总共包括了3部分的知识. 第1部分,基本概念 包括"并发.同步.主内存.本地内存.重排序.内存屏障.happens befo ...

  9. 深入理解java内存模型系列文章

    转载关于java内存模型的系列文章,写的非常好. 深入理解java内存模型(一)--基础 深入理解java内存模型(二)--重排序 深入理解java内存模型(三)--顺序一致性 深入理解java内存模 ...

  10. 【Todo】【转载】深入理解Java内存模型

    提纲挈领地说一下Java内存模型: 什么是Java内存模型 Java内存模型定义了一种多线程访问Java内存的规范.Java内存模型要完整讲不是这里几句话能说清楚的,我简单总结一下Java内存模型的几 ...

随机推荐

  1. C语言位操作--判断整数是否为2的幂

    unsigned int v; // 判断v是否为2的幂 bool f; // f为判断的结果 f = (v & (v - 1)) == 0; // 结果为0表示不是2 的幂 // 改变表示方 ...

  2. Unity3D笔记 模型和角色动画的输出设置

  3. Unity3D笔记 切水果 一

    最终效果: 一.选择背景图片,选择GUI Texture 二.创建一个空的GameObject,然后添加背景音乐 三.创建GUISkin 四.主要代码 #pragma strict var myGUI ...

  4. iOS - 开源框架、项目和学习资料汇总(网络篇)

    网络连接 1. AFNetworking – ASI不升级以后,最多人用的网络连接开源库,[推荐]iOS网络编程之AFNetworking使用,iOS开发下载文件速度计算.2. Alamofire – ...

  5. 170822、解决PLSQL记录被另一个用户锁住的问题

    1.查看数据库锁,诊断锁的来源及类型: select object_id,session_id,locked_mode from v$locked_object; 或者用以下命令: select b. ...

  6. Oracle中的时间函数用法(to_date、to_char) (总结)

    一.24小时的形式显示出来要用HH24 select to_char(sysdate,'yyyy-MM-dd HH24:mi:ss') from dual; select to_date('2005- ...

  7. CodeForces - 586D Phillip and Trains 搜索。vis 剪枝。

    http://codeforces.com/problemset/problem/586/D 题意:有一个3*n(n<100)的隧道.一个人在最左边,要走到最右边,每次他先向右移动一格,再上下移 ...

  8. iOS 项目架构tabbarController 嵌套 navbarController

    简单思路: 进入APP,首先加载 splashVC,加载完成之后,在viewDidAppear里跳转到loginVC,(这里一定要在viewDidLoad方法里新建loginVC跳转). 登陆成功之后 ...

  9. bzip2 zip 压缩后体积比 0.8:1

    1. 对.bz2 后缀文件 跳过不处理 2.逐行同字段的json文件,压缩后大小为原文件的12.81% 测试文件近似认为为逐行json文本数据,没有进行多文件重复测试,没有统计时间: {"u ...

  10. abi-api, arm target triplet https://en.wikipedia.org/wiki/ARM_architecture

    GNU软件用target triplet来描述工作平台,target triplet是一种规范化的名称,形如cpu-vendor-os(where os can be ‘system’ or ‘ker ...