要解决的问题

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

    Virgo Tomcat Server简称VTS,VTS是一个应用服务器,它是轻量级, 模块化, 基于OSGi系统.与OSGi紧密结合并且可以开发bundles形式的Spring web apps应用 ...

  2. [工具] 知网(CNKI)文献下载工具

    https://github.com/amyhaber/cnki-downloader 用于免费搜索,下载CNKI上的各类文献资料

  3. [实战]MVC5+EF6+MySql企业网盘实战(2)——用户注册

    写在前面 上篇文章简单介绍了项目的结构,这篇文章将实现用户的注册.当然关于漂亮的ui,这在追后再去添加了,先将功能实现.也许代码中有不合适的地方,也只有在之后慢慢去优化了. 系列文章 [EF]vs15 ...

  4. PAT甲1038 Recover the smallest number

    1038 Recover the Smallest Number (30 分) Given a collection of number segments, you are supposed to r ...

  5. 一个sfm开源项目

    Structure from Motion 资料总结 https://blog.csdn.net/u014636245/article/details/77527627 github上用opencv实 ...

  6. 2018-2019-2 20165330《网络对抗技术》Exp3 免杀原理与实践

    目录 基础问题 相关知识 实验内容 实验步骤 实验过程中遇到的问题 离实战还缺些什么技术或步骤? 实验总结与体会 实验内容 正确使用msf编码器,msfvenom生成如jar之类的其他文件,veil- ...

  7. 2018牛客网暑期ACM多校训练营(第二场) J - farm - [随机数哈希+二维树状数组]

    题目链接:https://www.nowcoder.com/acm/contest/140/J 时间限制:C/C++ 4秒,其他语言8秒 空间限制:C/C++ 262144K,其他语言524288K ...

  8. Python的浅拷贝与深拷贝

    定义: =号浅拷贝:在Python中对象的赋值其实就是对象的引用.copy了之后两个仍然是同一个东西.那么他们内部的元素自然也是一样的,对其中一个进行修改,另一个也会跟着变> copy()浅拷贝 ...

  9. How to disable a plugin when Jenkins is down?

    ===(different .jpi and bak and restore it )=== A plugin is preventing Jenkins to restart Environment ...

  10. nginx之配置proxy_set_header

    win10客户端请求web服务,win10的ip:192.168.223.1 nginx作为反向代理服务器:192.168.223.136 nginx作为后端web服务器:192.168.223.13 ...