Java 内存模型

362 阅读5分钟

这是我参与8月更文挑战的第18天,活动详情查看:8月更文挑战

Java 内存模型

接下来咱们进入 Java 内存模型的学习,咱们的学习目标有两个,学习 Java内存模型的概念和它的作用。

咱们先来看 Java 内存模型的概念,它全称叫做 Java Memory Model,翻译成中文就叫做 Java 内存模型。一般我们都会简称 JMM。

Java 完内存模型现在也是面试的一个热点话题,值得注意的是 Java 内存模型千万不要和 JJava 内存结构混淆。以前我们学 Java 的时候知道 JVM 会对内存等进行划分,会发划分成栈堆、方法区等等,这个指的是 Java 内存结构。

Java 内存模型是一套规范,关于 Java 内存模型的权威解释,可以参考这个网址 download.oracle.com/otn-pub/jcp…。是 Oracle官方提供的一个纯英文的版本文档,这个就是 Java 内存模型的详细的说明文档,它其实是一套规范,这套规范它主要在说两个关键字,一个是 synchronized,一个是 volatile。

温馨提示:有兴趣的可以去读一读这个文档,对大家来说还是非常有帮助的。

为什么会出现 Java 内存模型呢?我们知道 Java 是一门跨平台的语言,可以在不同的操作系统上运行,底层是依赖 JVM 虚拟机来进行跨平台的,每个平台都有一个对应的虚拟机,我们 Java 程序就可以运行在不同的操作系统上。

Java 内存模型是 Java 虚拟机规范中的一部分,主要是用来屏蔽我们 Java 程序运行在不同操作系统上的一些细节问题。让我们的 Java 程序只要关注这个 Java 完内存模型。Java 内存模型是一套规范,描述的是我们加法中各种变量,主要是线程共享变量的访问规则。它主要描述 Java 中变量存储和读取的底层细节。

image-20210118060753656

Java 内存模型把内存分成两部分,一部分做主内存,另外一部分呢叫做工作内存。

首先们看主内存,我们 Java 中的共享变量都放在主内存中,比如说类的成员变量,我们也叫实例变量。还有静态的成员变量或者说叫类变量,都存在主内存中,每个线程都可以来访问主内存。

接着我们看第二部分工作内存,每个线程都有它自己的工作内存,当我们线程要执行代码的时候,必须在工作内存中进行处理。举个例子,假设我们线程要访问一个共享变量 X,要对它进行操作,那么线程它是不能直接在主内存中来操作共享变量的,要怎么办呢?它必须把这个共享变量先复制一份放到自己的工作内存,然后再进行数据的处理,处理完之后再同步回这个主内存来。

假设线程1 想对共享变量进行操作,这里有个共享变量 int X = 10,那么首先这个线程它要把共享变量拷贝一份,放到自己的工作内存,然后进行处理。假设处理完之后,它要把这个处理完的结果同步回主内存,然后其他的线程也是一样的,先要把这个共享变量有主内存拷贝一份到自己的工作内存,然后再去进行操作,最后再同步回来。

那么接着我们来这边详细的看一下主内存,它是所有线程共享的数据,都能访问的。主要就是包含类里面的成员变量,包括静态的采用变量。注意线程的局部变量是不会再主内存的,因为线程的局部变量是不是只有某个线程自己能用。工作内存就是每个线程都有工作内存,然后工作内存会放这个共享变量的副本,线程对共享变量的所有操作都是先对这个副本进行操作,操作完之后再同步回这个主内存。

接着我们来看 Java 内存模型的作用。Java 存模型是一套规范,主要的目的就是在多线程对共享变量进行读写时,来保证共享变量的可见性、有序性还有原子性。Java 存模型这套规范里面主要就产生了两个关键字,一个是 synchronized,另外一个是 volatile。我们编程的时候也是通过这两个关键字去保证它的这三个特性。

咱们了解了 Java 内存模型后,有的小伙伴可能就有疑问了,这个 Java完内存模型跟真实的计算机的内存结构有什么关系呢?

image-20210118063402516

首先看上图的右边,这是我们真实的计算机的硬件架构,有 CPU,CPU 里面有寄存器、还有缓存、还有内存。然后左边是咱们的 Java 内存模型。知道 Java内存模型它是一套抽象出来的规范,一套抽象的概念。Java 内存模型中的工作内存,它有可能对应的是 CPU 的寄存器,也有可能对 CPU 的缓存,也有可能对内存。Java 内存模型中的主内存,也有可能对应 CPU 的寄存器,也有可能对于缓存,也有可能对应内存。

小结:到此,咱们就学习完了 Java 内存模型的概念和作用,咱们来进行一个小结,咱们知道 Java 内存模型是一套规范。主要是来让我们 Java 程序可以跨平台,然后又不又不需要关注平台的底层的细节。Java 内存模型描述了各种各样的变量的访问规则,Java 内存模型可以保证我们多线程操作共享数据时,解决了可见性、有序性和原子性的问题。