java内存模型

java内存模型

一、堆Heap、栈stack

  1. Java把内存划分成两种:一种是栈内存,一种是堆内存。
    堆内存:主要存储new创建的对象(类实例)和数组,由Java虚拟机(JVM)的垃圾回收器来管理。
    栈内存:函数中定义的基本类型变量和对象的引用变量。
    在堆中创建一个后,还可在栈中定义一个特殊的变量,这个变量的值=对象或数组在堆内存中的首地址,这个变量也就是我们常说的数组或对象的引用变量,以后就可以在程序中使用栈内存中的引用变量来访问堆中数据。如果数组和对象没有引用变量指向便不能再被使用,相当于垃圾但是仍然占着内存(也是java比较占内存的主要原因),在随后的一个不确定的时间会被垃圾回收器释放掉。栈中的变量指向堆内存中的变量,这就是 Java 中的指针!可以这么理解,堆主要用来存放数据,栈主要是用来执行程序。
  2. 堆特点:它能动态分配内存的大小,分配的内存不需要代码进行显示的释放,垃圾回收器会处理,生存期也不必事先告诉编译器(因为是运行时动态分配内存),但由于要在运行时动态分配内存,则存取速度较慢。
    栈特点:存取速度比堆要快,仅次于寄存器,栈数据可以共享。但栈中的数据大小和生存期必须是确定的,缺乏灵活性。
  3. JVM是基于堆栈的虚拟机,主要管理两种类型内存:堆和非堆。
    堆内存:在 Java 虚拟机启动时创建。储存前面所说的对象和数组,是一个运行时数据区。
    非堆内存:在JVM堆之外的内存,简单来说包含方法区、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法的代码、JVM内部处理或优化所需的内存。

二、涉及多线程编程

  1. 内存模型相关概念
    计算机在执行程序时每条指令都是在cpu中执行,而执行指令大都就涉及数据读取修改写入,临时数据,而程序运行过程中临时数据存放于主存(物理内存),而cpu执行速度很快,而从内存的读取速度不会那么快,那么如果涉及到数据操作都要与主存进行交互就会大大降低指令执行速度,于是就有了高速缓存。程序运行时,会将需要运算的数据从主存复制一份到高速缓存进行计算,结束后再将高速缓存中的数据刷新到主存中。
    比如 i = i + 1;
    当线程执行这个语句时,会先从主存当中读取i的值,然后复制一份到高速缓存当中,然后CPU执行指令对i进行加1操作,然后将数据写入高速缓存,最后将高速缓存中i最新的值刷新到主存当中。这个在单线程中运行是没有任何问题的,但是在多线程中运行就会有问题了。在多核CPU中,每条线程可能运行于不同的CPU中,因此每个线程运行时有自己的高速缓存(对单核CPU来说也会出现这种问题)。
    假设同时有2个线程执行这段代码,i初始值为0我们希望两个线程执行完之后i的值变为2。而不尽然,可能会出现这种情况:两个线程分别读取i的值存入各自所在的CPU的高速缓存当中,然后线程1进行加1操作,然后把i的最新值1写入到内存。而此时线程2的高速缓存当中i的值还是0,进行加1操作之后,i的值为1,然后线程2把i的值写入内存。所以最终结果i=1,而不是2。这就是著名的缓存一致性问题。通常称这种被多个线程访问的变量为共享变量。
    也就是说,如果一个变量在多个CPU中都存在缓存(一般在多线程编程时才会出现),那么就可能存在缓存不一致的问题。在硬件层面上有提供以下两种方式来解决
    1.通过在总线加LOCK#锁的方式
    2.通过缓存一致性协议,比如Intel 的MESI协议
  2. java内存模型给多线程编程的一些保证
    上面说了一些关于内存模型以及并发编程中可能会出现的一些问题。下面就来看一下Java内存模型。
    在Java虚拟机规范中试图定义一种Java内存模型(Java Memory Model,JMM)来屏蔽各个硬件平台和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的内存访问效果。Java内存模型规定所有的变量都是存在主存当中(类似于前面说的物理内存),每个线程都有自己的工作内存(类似于前面的高速缓存)。线程对变量的所有操作都必须在工作内存中进行,而不能直接对主存进行操作。并且每个线程不能访问其他线程的工作内存,则也会存在缓存一致性问题。
    那么Java内存模型是如何解决这些问题,它又为多线程编程要注意的三条特性提供了哪些保证呢。
    1.java中只对基本数据类型的变量读取和赋值(局限于i = 1这种形式,变量之间的赋值不算)具有原子性。
    2.java提供了synchonized和Lock可以确保原子性,可见性,有序性
    3.java还提供了volatile关键字确保变量的可见性,也保证了一定“有序性”,意思是说,volatile修饰的变量之前的指令肯定先于它被执行,而它之后的指令肯定会后于它执行。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章