Java 内存模型规定了 Java 虚拟机如何与计算机内存 (RAM) 协同工作。Java 虚拟机是整个计算机的模型,因此该模型自然包含一个内存模型,也就是 Java 内存模型。
如果你想设计出性能良好的并发程序,理解 Java 内存模型至关重要。Java 内存模型规定了不同线程如何以及何时可以访问其他线程写入共享变量的值,以及如何在必要时同步对共享变量的访问。
原始的 Java 内存模型存在不足,因此 Java 1.5 中对 Java 内存模型进行了修订。此版本的 Java 内存模型至今仍在 Java 中使用(Java 14+)。
Java内部内存模型
JVM 内部使用的 Java 内存模型将内存划分为线程栈和堆。下图从逻辑角度展示了 Java 内存模型:
Java 虚拟机中运行的每个线程都有自己的线程堆栈。线程堆栈包含线程调用了哪些方法到达当前执行点的信息。我将其称为“调用堆栈”。随着线程执行其代码,调用堆栈会发生变化。
线程堆栈还包含每个正在执行的方法(调用堆栈上的所有方法)的所有局部变量。每个线程只能访问其自己的线程堆栈。线程创建的局部变量对创建该线程的所有其他线程都是不可见的。即使两个线程执行完全相同的代码,这两个线程仍会在各自的线程堆栈中创建该代码的局部变量。因此,每个线程都有其各自版本的局部变量。
所有原始类型( boolean
、byte
、short
、char
、int
、long
、 ) 的局部变量 都完全存储在线程堆栈中,因此对其他线程不可见。一个线程可以将原始变量的副本传递给另一个线程,但不能共享原始局部变量本身。 float``double
堆包含 Java 应用程序中创建的所有对象,无论该对象是由哪个线程创建的。这包括原始类型的对象版本(例如、Byte
等)。无论对象是创建后赋值给局部变量,还是作为另一个对象的成员变量创建,该对象仍然存储在堆中。 Integer``Long
下图展示了调用堆栈和存储在线程堆栈上的局部变量以及存储在堆上的对象:
局部变量可能是原始类型,在这种情况下它完全保存在线程堆栈上。
局部变量也可以是对象的引用。在这种情况下,引用(局部变量)存储在线程堆栈上,但对象本身存储在堆上。
对象可能包含方法,而这些方法可能包含局部变量。即使方法所属的对象存储在堆上,这些局部变量也存储在线程堆栈上。
对象的成员变量与对象本身一起存储在堆上。无论成员变量是原始类型,还是对象的引用,都是