前面介绍了计算机内存模型,这是解决多线程场景下并发问题的一个重要规范。
那么具体的实现是如何的呢?不同的编程语言,在实现上可能有所不同。
我们知道,Java 程序是需要运行在 Java 虚拟机上面的,Java 内存模型(Java Memory Model,JMM)就是一种符合内存模型规范的,屏蔽了各种硬件和操作系统的访问差异的,保证了Java 程序在各种平台下对内存的访问都能保证效果一致的机制及规范。
提到 Java 内存模型,一般指的是 JDK 5 开始使用的新内存模型,主要由 JSR-133:JavaTM Memory Model and Thread Specification 描述。
Java 内存模型规定了所有的变量都存储在主内存中,每条线程还有自己的工作内存。
线程的工作内存中保存了该线程中用到的变量的主内存副本拷贝,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存。
不同的线程之间也无法直接访问对方工作内存中的变量,线程间变量的传递均需要自己的工作内存和主存之间进行数据同步进行。
而 JMM 就作用于工作内存和主存之间数据同步过程。它规定了如何做数据同步以及什么时候做数据同步。
这里面提到的主内存和工作内存,读者可以简单的类比成计算机内存模型中的主存和缓存的概念。
特别需要注意的是,主内存和工作内存与 JVM 内存结构中的 Java 堆、栈、方法区等并不是同一个层次的内存划分,无法直接类比。
《深入理解Java虚拟机》中认为:如果一定要勉强对应起来的话,从变量、主内存、工作内存的定义来看,主内存主要对应于 Java 堆中的对象实例数据部分。而工作内存则对应于虚拟机栈中的部分区域。
所以,再来总结下,JMM 是一种规范,是解决由于多线程通过共享内存进行通信时,存在的本地内存数据不一致、编译器会对代码指令重排序、处理器会对代码乱序执行等带来的问题。
目的是保证并发编程场景中的原子性、可见性和有序性。
Java 内存模型的实现
了解 Java 多线程的朋友都知道,在 Java 中提供了一系列和并发处理相关的关键字,比如 Volatile、Synchronized、Final、Concurren 包等。
其实这些就是 Java 内存模型封装了底层的实现后提供给程序员使用的一些关键字。
在开发多线程的代码的时候,我们可以直接使用 Synchronized 等关键字来控制并发,这样就不需要关心底层的编译器优化、缓存一致性等问题。
所以,Java 内存模型,除了定义了一套规范,还提供了一系列原语,封装了底层实现后,供开发者直接使用。