天天看點

java記憶體模型 JMM詳解

什麼是java記憶體模型 或者說JMM模型

  這個新手特别容易混淆,記憶體模型不是JVM記憶體模型!

  • JMM是一種抽象的概念,并不真實存在,是一組規範或者規則;關注的是多個線程對共享記憶體空間和線程私有工作空間的通路方式,圍繞并發的原子性、有序性、可見性來展開的,想要了解JAVA的并發程式設計,就應該了解JMM。
  • JMM通過定義了對變量(包括執行個體成員、靜态成員群組成數組對象的元素)的通路方式,在程式運作時,運作程式的是實體是線程,每個線程建立時候,虛拟機都會為每個線程配置設定一定的記憶體空間,每個線程的記憶體空間用來存儲線程私有的資料。但是JMM中規定資料都是存儲在共享的主記憶體空間,而且每個線程不能直接操作主記憶體的空間,隻能通路主記憶體的空間,且每個線程可以操作自己的工作空間,是以每個線程将自己用到的資料從共享的主記憶體空間中拷貝一份到其工作空間,操作完之後回寫到主記憶體空間。
  • 在JMM模型中,初步的劃分了工作記憶體和主記憶體。并且明确了一件事,線程中的工作空間是私有的,線程之間不能通路對方的工作空間。主記憶體是存放的是共享記憶體,由線程共享。

最終的線程模型如下

java記憶體模型 JMM詳解

 JMM 與 JVM的關系

  JMM是Java記憶體模型,既然是模型,JMM規範指導産出了JVM,JVM正是根據JMM在實體記憶體劃分出的結果。Java記憶體模型的作用是規範記憶體資料和工作空間資料的互動 。

java記憶體模型 JMM詳解

   1、MM中記憶體有共享的記憶體空間和線程私有的工作空間,JVM運作時資料區有  方法區、堆、本地方法棧、虛拟機棧、程式計數器

   2、JVM運作時資料區共享的記憶體空間有   方法區和堆,是以可以了解  JMM的共享記憶體區域包含了 方法區和棧。JMM的線程私有空間包含了  程式計數器、本地方法棧、虛拟機棧

 這裡插一個問題,我記得阿裡的面試官問過,你知道JVM記憶體模型嗎?那你知道為什麼這樣劃分嗎?在這裡我覺得 JMM就是JVM為什麼這樣劃分的一個答案。

Java記憶體模型與硬體記憶體架構的關系

   因為JMM隻是一種抽象的概念,是一組規則,并不實際存在,不管是工作記憶體的資料還是主記憶體的資料,對于計算機硬體來說都會存儲在計算機主記憶體、CPU緩存和CPU寄存器中,是以Java記憶體模型和計算機硬體記憶體架構是一個互相交叉的關系,是一種抽象概念劃分與真實實體硬體的交叉。

java記憶體模型 JMM詳解

計算機硬體架構存在的問題:

多個CPU并行處理緩存資料時,并發處理的不同步,會産生資料一緻性問題。

解決方案:

Ⅰ. 總線加鎖:CPU核執行一個線程去通路資料做操作的時候,向總線上發送一個LOCK信号,通過把記憶體和CPU之間的通信鎖住,把并行化的操作變成了串行。雖然能解決一緻性問題,但是會導緻很嚴重的性能問題。

Ⅱ. 緩存的一緻性協定(MESI):當CPU在Cache中操作資料時,如果該資料是共享變量,資料在Cache讀到寄存器中,進行新修改,并更新記憶體資料Cache Line置無效。其他的CPU拿取資料,若Cache Line為無效會從記憶體中拿取。

JAVA記憶體模型資料同步8大原子操作 

1、8大原子操作:

     lock(鎖定):把一個變量标記為一條線程獨占狀态

     unlock(解鎖):把一個處于鎖定狀态的變量釋放出來,釋放後的變量才可以被其他線程鎖定

     read(讀取):把主記憶體中的一個變量讀取傳輸到線程的工作記憶體,以便随後load動作使用

     load(加載):把read到線程工作記憶體的變量放入工作記憶體的變量副本中

     use(使用):把線程工作記憶體中的一個變量值傳遞給執行引擎

     assign(指派):從執行引擎接收到的新值指派給變量。返給工作記憶體

     store(存儲):把線程工作記憶體的一個變量值傳遞給主記憶體,以便後面的write使用

     write(寫入):把store到主記憶體的變量值指派給變量