在Java虚拟机中定义了一种内存模型也就是JMM。目的是屏蔽各种硬件和操作系统的内存差异,以解决Java跨平台时能达到统一的内存访问效果。下面我们了解一下在JMM中内存是怎么划分的。
JMM的目的就是为了解决程序中各个变量的访问规则,也就是虚拟机将变量存储到内存和从内存中读取变量的底层实现。但这里面所说的变量只包括实例变量和静态变量,并不包括局部变量。因为局部变量是线程私有的,并不会被其它线程所共享。所以不存在数据竞争的问题,所以在多线程执行时,局部变量是不会出线线程安全问题的。既然实例变量和静态变量是被所有线程共享的,那么在JMM中虚拟机是怎么保证在线程程执行时,变量的线程安全呢?
在JMM中有一个规定就是所有变量都必须存储在主内存中。主内存也就是虚拟机内存的一部分区域。除此之外,每一个线程都有自己独立的工作内存。线程工作内存与主内存的区别是?线程在执行时会把所需要的变量从主内存拷贝到工作内存中。线程对变量的所有操作包括读取、赋值等都必须在线程自己的工作内存中进行,而不能直接操作主内存中的变量。不同线程与线程间的是无法直接访问对方工作内存中的变量的。如果某一个线程需要访问其它线程工作内存中的变量时,它们只能通过主内存来完成。下图是线程与工作内存、主内存之间的关系图。
上述所说的主内存和工作内存与并不是我们常说的虚拟机中的堆、 栈、 方法区等。它们并不是一个内存概念。为了方便理解我们可以认为主内存就是虚拟机堆中的存储对象实例的内存,而工作内存就是虚拟机栈中的内存。
下面我们来详细了解一下,一个变量是怎么从主内存拷贝到线程的工作内存中的。在JMM中主要定义了8种操作来完成上述的工作,并且这8种操作都是原子性的,不可分割的。它们分别是:
上述就是每种操作的具体功能。按照上述的规则。如果要把变量从主内存复制到工作内存中那就要顺序地执行read和load操作,如果要把变量从工作内存同步回主内存时,就要顺序地执行store和write操作。 在虚拟机执行上述操作时有一些默认的规定,它们具体是。