java內存模型與線程(二)

Java內存模型:
   Java虛擬機規範中試圖定義一種java內存模型(Java Memory Model,JMM)來屏蔽掉各類硬件和操做系統的內存訪問差別,以實現讓Java程序在各個平臺下都能達到一致的內存訪問效果。Jdk1.5(實現了JSR-133)發佈後,java內存模型才成熟和完善起來。
1、主內存和工做內存:
  java內存模型的主要目標是定義程序中的各個變量的訪問規則,即在虛擬機中將變量存儲到內存和從內存中取出變量這樣的底層細節。
  java內存模型規定了全部的變量都存儲在主內存中(虛擬機內存的一部分)。每一個線程還有本身的工做內存,線程的工做內存中保存了 該線程使用到的變量的主內存的副本拷貝,線程對變量的全部操做都必須在工做內存中進行,而不能直接讀寫主內存中的變量。線程間的變量值的傳遞都須要經過主內存來完成。
  線程、主內存、工做內存三者交互關係圖以下: java

 


2、內存間交互操做:
  Java內存模型定義了8種操做來完成主內存和工做內存之間的交互協議,即一個變量如何從主內存拷貝到工做內存、如何從工做內存同步回主內存的實現細節。虛擬機保證了下面的每一種操做的原子性、不可再分。
  lock(鎖定):做用於主內存的變量,它把一個變量標識爲一條線程獨佔的狀態。
  unlock(解鎖):做用於主內存變量,它把一個處於鎖定狀態的變量釋放出來。
  read(讀):做用於主內存的變量,它把一個變量的值從主內存傳輸到線程的工做內存中,以便隨後的load動做。
  load(載入):做用於工做內存的變量,它把read操做的變量值放入工做內存的變量副本中。
  use(使用):做用於工做內存的變量,它把工做內存的一個變量的值傳遞給執行引擎,
              每當虛擬機遇到一個須要使用到變量的值的字節碼指令的時候會執行這個操做。
  assign(賦值):做用於工做內存的變量,它把一個從執行引擎接收到的值賦給工做內存的變量,
              每當虛擬機遇到一個給變量賦值的字節碼指令時執行這個操做。
  store(存儲):做用於工做內存的變量,它把一個工做內存中的變量的值傳送到主內存中,以便隨後的write操做。
  write(寫入):做用於主內存的變量,它把store操做從工做內存中取到的變量的值放入到主內存的變量中。 安全

   關係圖: 併發

 

  若是要把一個變量從主內存複製到工做內存,那就要順序的執行read、load操做;
  若是要把一個變量從工做內存同步到主內存,那就要順序的執行store、write操做。
  java內存模型只要求上述的兩個操做必須按順序執行,而沒有保證必須是連續的執行。也就是說read和load之間、store和write之間是能夠插入其餘指令的。
  同時java內存模型還規定了在執行上述的8中基本操做的時候必須知足以下規則: spa


  2.1 不容許read和load、store和write操做之一單獨出現,即不容許一個變量從主內存讀取到了可是工做內存不接受,
      或者從工做內存發起了回寫可是主內存不接受的狀況出現。
  2.2 不容許一個線程丟棄它的最近的assign操做,即變量在工做內存中改變了以後必須把該變化同步到主內存。
  2.3 不容許一個線程無緣由(沒有發生過任何assign操做)的把數據從線程的工做內存同步到主內存中。
  2.4 一個新的變量只能在主內存中誕生,不容許工做內存中直接使用一個未被初始化(load或assign)的變量,
      也就是說對一個變量的user、store操做以前,必須限制性load和assign操做。
  2.5 一個變量在同一時刻只容許一條線程對其進行lock操做,但lock操做能夠被同一條線程重複執行屢次,
      屢次執行lock後,要進行相同次數的unlock操做,變量纔會被解鎖。
  2.6 若是對一個變量執行lock操做,那將會清空工做內存中此變量的值,在執行引擎使用這個變量前,
      須要從新執行load或assign操做初始化變量的值。
  2.7 若是一個變量事先沒被lock操做鎖定,那就不容許對他執行unlock操做,也不容許unlock一個唄其餘線程鎖定住的變量。
  2.8 對一個變量執行unlock操做以前,必須先把此變量同步到主內存中(執行store、write操做)。
  這8種內存訪問操做以及上述的限定,再加上volatile(後續介紹)的一些特殊限定,就已經徹底肯定了java程序中哪些內存訪問操做在併發下是安全的。 操作系統

參考:深刻理解Java虛擬機(周志明 著) 線程

相關文章
相關標籤/搜索