JVM学习笔记——java内存模型

概述

JVM规范但愿定义一套java内存模型(java memory model,JMM),使得java程序在不一样的硬件平台下面都能展示出一致的内存访问机制。
java内存模型规定全部变量保存在主内存中,每一个线程有本身的工做内存。线程的工做内存中保存了该线程使用到的变量的主内存拷贝,线程对变量的全部操做都必须在工做内存中进行,而不能直接读写主内存中的变量。不一样的线程之间没法直接访问对方的工做内存,需经过主内存才能进行变量的传递。java内存模型围绕原子性有序性可见性三个方面展开。
java

内存间交互操做

关于变量在工做内存和主内存之间的传递,java内存模型定义了如下8种原子操做:架构

  1. lock:做用于主内存变量
  2. unlock:做用于主内存变量
  3. read:做用于主内存变量
  4. load:做用于工做内存变量
  5. use:做用工做内存变量
  6. assign:做用于工做内存变量
  7. store:做用于工做内存变量
  8. write:做用于主内存变量
    JVM保证了以上8种操做的原子性。这8种操做还有一些特殊的规则:

volatile变量保证了可见性与有序性,volatile变量的操做也须要遵循一些特殊的规则:jvm

先行发生原则:线程

基于栈的指令

JVM指令是基于栈的指令架构,与之相对的是基于寄存器的指令,如x86平台。基于栈的指令集的优势是可移植,缺点是执行速度慢。

下面的基于栈的指令例子中,也有load、store等操做,这些属于工做内存中的操做,与内存之间的那8种原子操做不同。
咱们可使用javap -c去获取java代码的字节码。字节码是运行在JVM上的指令。咱们翻译一段简单的程序。看看基于栈的指令是如何工做的。翻译

public int calc() {
    int a = 100;
    int b = 200;
    int c = 300;
    return (a+b)*c;
}
public int calc();
    Code:
       0: bipush        100
       2: istore_1
       3: sipush        200
       6: istore_2
       7: sipush        300
      10: istore_3
      11: iload_1
      12: iload_2
      13: iadd
      14: iload_3
      15: imul
      16: ireturn







volatile的JVM指令

我试着去比较带volatile的程序和不带volatile的程序,javap以后显示,它们的字节码是没有区别的。若是咱们再深刻一层去看JIT以后的跟CPU强相关的指令,应该会发现不一样。3d

相关文章
相关标签/搜索