JVM規範但願定義一套java內存模型(java memory model,JMM),使得java程序在不一樣的硬件平臺下面都能展示出一致的內存訪問機制。
java內存模型規定全部變量保存在主內存中,每一個線程有本身的工做內存。線程的工做內存中保存了該線程使用到的變量的主內存拷貝,線程對變量的全部操做都必須在工做內存中進行,而不能直接讀寫主內存中的變量。不一樣的線程之間沒法直接訪問對方的工做內存,需經過主內存才能進行變量的傳遞。java內存模型圍繞原子性、有序性、可見性三個方面展開。
java
關於變量在工做內存和主內存之間的傳遞,java內存模型定義瞭如下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的程序和不帶volatile的程序,javap以後顯示,它們的字節碼是沒有區別的。若是咱們再深刻一層去看JIT以後的跟CPU強相關的指令,應該會發現不一樣。3d