深刻理解Java虛擬機讀書筆記-第12章 Java內存模型與線程

第12章 Java內存模型與線程

12.1 概述

介紹虛擬機如何實現多線程,多線程之間因爲共享數據而致使的一系列問題及解決方案緩存

12.2 硬件效率與一致性

介紹Java虛擬機內存模型前,先了解下物理機的併發問題。安全

  • 硬件效率問題。計算機處理任務除了處理器計算外,還有內存交互,即讀寫數據。而存儲設備與處理機運行速度相差幾個數量級,爲此引入了讀寫速度儘量接近處理器的高速緩存Cache。處理器讀寫緩存數據,緩存將數據同步到內存。
  • 緩存一致性問題。在共享內存多核系統中,每一個處理器都有本身的高速緩存,又共享同一主內存。爲了解決一致性問題,處理器訪問高速緩存時,須要遵循一些協議,好比MSI,MESI,MISI,Synapse,Dragon Protocol等。
  • 代碼亂序執行優化問題。處理器爲了提升運算效率,會出現不按順序執行的狀況,但單線程下,處理器會保證執行結果與順序執行結果一致。而多線程的狀況下,沒法保證多個任務都按照順序執行。

Java虛擬機有本身的內存模型,也會有與物理機類型的問題。markdown

截屏2020-09-01上午9.38.11.png

12.3 Java內存模型

12.3.1 概述

Java內存模型規定:因此變量都存儲在主內存(Main Memory)中,線程有本身的工做內存,工做內存保存變量在主內存副本。線程對變量的讀寫只能再工做內存(Working Memory)中,線程間共享變量須要經過主內存完成。
  JVM內存模型的執行處理將圍繞解決兩個問題展開:
複製代碼
  • 工做內存數據一致性
  • 指令重排序優化,編譯期重排序和運行期重排序。

截屏2020-09-01上午9.37.19.png

12.3.2 內存交互操做

主內存與工做內存的交互協議定義以下操做,Java虛擬機必須保證這些操做是原子性的。多線程

  • lock,做用於主內存變量,把變量標識爲線程獨佔狀態,使其餘線程沒法lock
  • unlock,做用於主內存變量,解除線程獨佔狀態
  • read,做用於主內存變量,把變量值傳輸到工做內存中,一邊隨後的load使用
  • load,做用於工做內存變量,把read的變量值放入工做內存的變量副本中。
  • use,做用於工做內存變量,變量值傳遞給執行引擎
  • assign,做用於工做內存變量,執行引擎賦值給工做內存中的變量
  • store,做用於工做內存變量,變量值傳輸到主內存,以便後續write使用
  • write,做用於主內存變量,把store的變量值放入主內存變量中。

截屏2020-09-01下午1.31.23.png 若是要把變量從主內存拷貝到工做內存,必須順序執行 read和load,但不要求必定連續。 若是要把變量從工做內存同步到主內存,必須順序執行 store和write,但不要求必定連續。併發

12.3.3 內存模型運行規則

1.內存交互基本操做的3個特性

Java內存模型是圍繞着在併發過程當中如何處理這3個特性來創建的,歸根結底是爲了實現共享變量在多個工做內存中的一致性,以及併發時,程序能如期運行。app

  • 原子性(Atomicity),即一個操做或者多個操做,要麼不執行,要麼所有執行且執行過程不會被打斷
  • 可見性(Visibility),當多個線程訪問同一個變量時,一個線程改變了變量值,其餘線程要能當即看到修改過的值。線程經過共享主內存實現可見性。
  • 有序性(Ordering),線程內指令串行(as-if-serial),線程間,對於同步(synchrinized)代碼以及volatile字段的操做須要維持相對有序

2.先行發生原則

happens-before優化

  • 程序次序規則
  • 管程鎖定規則
  • volatile變量規則
  • 線程啓動規則
  • 線程終止規則
  • 線程中斷規則
  • 對象終結規則
  • 傳遞性

3.內存屏障

內存屏障是被插入到兩個CPU指令之間的一種指令,用來禁止處理器指令發生指令重排序。spa

12.3.4 volatile型變量

volatile主要有下面兩種語義線程

語義1 保證可見性

保證了不一樣線程對該volatile型變量操做的內存可見性,但不等同於併發操做的安全性code

  • 線程寫volatile變量的過程assign-store-write必須連續出現:
    • 改變工做內存中volatile變量副本的值
    • 將改變的副本值刷新到主內存中
  • 線程讀volatile變量的過程read-load-use必須連續出現:
    • 從主內存讀取volatile變量值並存入工做線程副本
    • 從工做內存讀取變量副本

語義2 禁止指令重排序截屏2020-09-01下午2.22.56.png

volatile型變量使用場景總結起來就是"一次寫入,處處讀取",某個線程負責更新變量,其餘線程只讀取變量,並根據變量新值執行相應邏輯,例如狀態標誌位更新,觀察者模型變量值發佈

相關文章
相關標籤/搜索