JVM内存结构和Java内存模型

2020-05-19  本文已影响0人  浪够_

说到Java内存模型,许多文章就以栈、堆(heap)、方法区这些名词作为解释,但它们是两个完全不同的概念,或许将JVM内存结构和Java内存模型都解释为栈、堆,是因为程序员最关注的、与对象内存分配关系最密切的区域是“堆”和“栈”,“方法区”这些内存结构吧,姑且这么解释。但想深入理解JVM,就必须清楚JVM内存结构和Java内存模型分别是什么。

JVM内存结构

image

JVM的内存结构大概分为:

Java 内存模型

Java线程之间的通信由Java内存模型(本文简称为JMM)控制,它定义了程序中各种变量的访问规则。Java内存模型规定了所有的变量(此处的变量与Java编程中所说的变量有所区 别,它包括了实例字段、静态字段和构成数组对象的元素,但是不包括局部变量与方法参数,因为后者是线程私有的 ,不会被共享,自然就不会存在竞争问题) 都存储在主内存(Main Memory)中。每条线程还有自己的工作内存,线程的工作内存中保存了被该线程使用的变量的主内存副本,线程对变量的所有操作(读取、赋值等)都必须在工作内存中进行,而不能直接读写主内存中的数据 。不同的线程之间也无法直接访问对方工作内存中的变量,线程间变量值的传递均需要通过主内存来完成,线程、主内存、工作内存三者的交互关系如图122所示。


image.png

这里所讲的主内存、工作内存与所讲的Java内存区域中的Java堆、栈、方法区等并不是同一 个层次的对内存的划分,这两者基本上是没有任何关系的。如果两者一定要勉强对应起来,那么从变量、主内存、工作内存的定义来看,主内存主要对应于Java堆中的对象实例数据部分 ,而工作内存 则对应于虚拟机栈中的部分区域。从更基础的层次上说,主内存直接对应于物理硬件的内存,而为了 获取更好的运行速度,虚拟机(或者是硬件、操作系统本身的优化措施)可能会让工作内存优先存储 于寄存器和高速缓存中,因为程序运行时主要访问的是工作内存。

内存间交互操作

关于主内存与工作内存之间具体的交互协议,即一个变量如何从主内存拷贝到工作内存、如何从 工作内存同步回主内存这一类的实现细节,Java内存模型中定义了以下8种操作来完成。Java虚拟机实 现时必须保证下面提及的每一种操作都是原子的、不可再分的(对于double和long类型的变量来说,load、store、read和write操作在某些平台上允许有例外)

如果要把一个变量从主内存拷贝到工作内存,那就要按顺序执行read和load操作,如果要把变量从 工作内存同步回主内存,就要按顺序执行store和write操作。注意,Java内存模型只要求上述两个操作 必须按顺序执行,但不要求是连续执行。也就是说read与load之间、store与write之间是可插入其他指令 的,如对主内存中的变量a、b进行访问时,一种可能出现的顺序是read a、read b、load b、load a。除此 之外,Java内存模型还规定了在执行上述8种基本操作时必须满足如下规则:

这8种内存访问操作以及上述规则限定,再加上稍后会介绍的专门针对volatile的一些特殊规定,就 已经能准确地描述出Java程序中哪些内存访问操作在并发下才是安全的。这种定义相当严谨,但也是 极为烦琐,实践起来更是无比麻烦。可能部分读者阅读到这里已经对多线程开发产生恐惧感了,后来 Java设计团队大概也意识到了这个问题,将Java内存模型的操作简化为read、write、lock和unlock四 种,但这只是语言描述上的等价化简,Java内存模型的基础设计并未改变,即使是这四操作种,对于 普通用户来说阅读使用起来仍然并不方便。不过读者对此无须过分担忧,除了进行虚拟机开发的团队 外,大概没有其他开发人员会以这种方式来思考并发问题,我们只需要理解Java内存模型的定义即可。

上一篇 下一篇

猜你喜欢

热点阅读