> 文档中心 > Java内存模型JMM概述

Java内存模型JMM概述


1. JVM内存模型与java内存模型JMM的区别

JMM的定义: Java的并发采用的是共享内存模型 ,JMM是用来定义一个一致的、跨平台的内存模型,是缓存一致性协议,用来定义数据读写的规则。

JVM内存模型是处于Java的JVM虚拟机层面的,实际上对于操作系统来说,本质上JVM还是存在于主存中,而JMM是Java语言与OS和硬件架构层面的,主要作用是规定硬件架构与Java语言的内存模型,而本质上不存在JMM这个东西,JMM只是一种规范,并不能说是某些技术实现。

2. JMM结构规范

JMM规定了所有的变量都存储在主内存(Main Memory)中。每个线程还有自己的工作内存(Working Memory),线程的工作内存中保存了该线程使用到的变量的主内存的副本拷贝,线程对变量的所有操作(读取、赋值等)都必须在工作内存中进行,而不能直接读写主内存中的变量(volatile变量仍然有工作内存的拷贝,但是由于它特殊的操作顺序性规定,所以看起来如同直接在主内存中读写访问一般)。不同的线程之间也无法直接访问对方工作内存中的变量,线程之间值的传递都需要通过主内存来完成。

Java内存模型(即Java Memory Model,简称JMM)本身是一种抽象的概念,并不真实存在,它描述的是一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和构成数组对象的元素)的访问方式。

3. 举例理解

JMM与JVM内存区域的划分是不同的概念层次,在理解JMM的时候不要带着JVM的内存模型去理解,更恰当说JMM描述的是一组规则,通过这组规则控制程Java序中各个变量在共享数据区域和私有数据区域的访问方式.

 

4.  计算机硬件内存架构

正如上图所示(经过简化CPU与内存操作的简易图),实际上没有这么简单,这里为了理解方便,我们省去了南北桥。

就目前计算机而言,一般拥有多个CPU并且每个CPU可能存在多个核心,多核是指在一枚处理器(CPU)中集成两个或多个完整的计算引擎(内核),这样就可以支持多任务并行执行,从多线程的调度来说,每个线程都会映射到各个CPU核心中并行运行。在CPU内部有一组CPU寄存器,寄存器是cpu直接访问和处理的数据,是一个临时放数据的空间

一般CPU都会从内存取数据到寄存器,然后进行处理,但由于内存的处理速度远远低于CPU,导致CPU在处理指令时往往花费很多时间在等待内存做准备工作,于是在寄存器和主内存间添加了CPU缓存,CPU缓存比较小,但访问速度比主内存快得多,如果CPU总是操作主内存中的同一址地的数据,很容易影响CPU执行速度,此时CPU缓存就可以把从内存提取的数据暂时保存起来,如果寄存器要取内存中同一位置的数据,直接从缓存中提取,无需直接从主内存取。

需要注意的是,寄存器并不每次数据都可以从缓存中取得数据,万一不是同一个内存地址中的数据,那寄存器还必须直接绕过缓存从内存中取数据。所以并不每次都得到缓存中取数据,这种现象有个专业的名称叫做缓存的命中率,从缓存中取就命中,不从缓存中取从内存中取,就没命中,可见缓存命中率的高低也会影响CPU执行性能,这就是CPU、缓存以及主内存间的简要交互过程,总而言之当一个CPU需要访问主存时,会先读取一部分主存数据到CPU缓存(当然如果CPU缓存中存在需要的数据就会直接从缓存获取),进而在读取CPU缓存到寄存器,当CPU需要写数据到主存时,同样会先刷新寄存器中的数据到CPU缓存,然后再把数据刷新到主内存中。实则就类似于Appcalition(Java) --> Cache(Redis) --> DB(MySQL)的关系,Java程序的性能由于DB(数据库)需要走磁盘受到了影响,导致Java程序在处理请求时需要等到DB的处理结果,而此时负责处理该请求的线程一直处于阻塞等待状态,只有当DB处理结果返回了再继续负责工作,那么实际上整个模型中的问题是:DB的速度跟不上Java程序的性能,导致整个请求处理起来变的很慢,但是实际上在DB处理的过程Java的线程是处于阻塞不工作的状态的,那么实际上是没有必要的,因为这样最终会导致整体系统的吞吐量下降,此时我们可以加入Cache(Redis)来提升程序响应效率,从而整体提升系统吞吐和性能。(实际上我们做性能优化的目的就是让系统的每个层面处理的速度加快,而架构实际上就是设计一套能够吞吐更大量的请求的系统)。

java线程与OS(操作系统)

java内存模型与硬件内存架构的关系