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

相關文章
相關標籤/搜索