zoukankan      html  css  js  c++  java
  • JVM学习笔记——java内存模型

    概述

    JVM规范希望定义一套java内存模型(java memory model,JMM),使得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指令是基于栈的指令架构,与之相对的是基于寄存器的指令,如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强相关的指令,应该会发现不同。

  • 相关阅读:
    angularjs学习之六(angularjs中directive指令的一般编程事件绑定 模板使用等)
    Flex 容器基本概念
    flex 4 布局样式
    flex 特效
    delphi ehLib 安装包下载及安装方法
    CnPack IDE 专家包(CnWizards)显示代引用单元列表
    Delphi 获取DataSet传入参数后的SQL命令
    偶写的第一个控件,一个用选择代替输入的Edit控件…
    delphi中响应鼠标进入或离开控件的方法
    Delphi常用关键字用法详解
  • 原文地址:https://www.cnblogs.com/season-peng/p/7087742.html
Copyright © 2011-2022 走看看