今天簡單聊聊什麼叫作 Java 內存模型,不是 JVM 內存結構哦。java
JMM 是一個語言級別的內存模型,處理器的硬件模型是硬件級別,Java中的內存模型是內存可見性的基本保證。從而爲咱們 volatile 實現內存可見性提供了基石。主要目的就是讓 Java 程序員在各類平臺下達到一致性訪問效果程序員
JMM決定一個線程對共享變量的寫入什麼時候對另外一個線程可見,尤爲是在對共享變量的讀寫,修改後其餘線程馬上內讀取到,這個就是JMM主要做用。從抽象的角度來看,JMM定義了線程和主內存之間的抽象關係:線程之間的共享變量存儲在主內存(Main Memory)中,每一個線程都有一個私有的本地內存(Local Memory),本地內存中存儲了該線程以讀/寫共享變量的副本。本地內存是JMM的一個抽象概念,並不真實存在。它涵蓋了緩存、寫緩衝區、寄存器以及其餘的硬件和編譯器優化。Java內存模型的抽象示意如圖所示。緩存
前面咱們說到 volatile 底層原理詳解,這個語義的實現就是利用了Java的內存模型。爲咱們屏蔽了細節,實現了內存可見性,有興趣的讀者能夠看公衆號前期發的文章 volatile 底層原理實現。app
爲何須要JMM?性能
在執行程序的時候,爲了提升性能,編譯器與處理器常會對指令進行重排序優化,保證執行結果與書序執行的結果是一致的,但並不能保證各個語句執行的前後順序與輸入的代碼順序一致。(固然是說在單線程的狀況下)。優化
因此有 volatile 修飾的代碼就不會被指令重排,至關於加了一道內存屏障,不能把後面的指令重排序到內存屏障以前。spa
Happens-before定義:線程
- 若是一個操做 Happens-before 另外一個操做,那麼第一個操做的執行結果將對第二個操做可見,並且第一個操做的執行順序在第二個操做以前。
- 兩個操做之間存在 Happens-before 關係,並不意味着必須按照代碼指定順序執行。若是重排序後的執行結果與按照 Happens-before 結果執行的結果一致,那也是能夠的。
先行發生是 Java 內存模型中定義的兩項操做之間的偏序關係,若是說操做A先行發生於B,其實就是說在發生操做 B 以前,操做 A 產生的影響能被 B 觀察到, 「影響」 包括修改了內存中共享變量的值、發送了消息、調用了方法。好比:3d
//在線程 A 執行 1
i = 2;`
// 在線程 B 執行 2
j = i;`
// 在線程 C 執行 3
i = 3;
複製代碼
假設執行順序是 1 -> 3 -> 2:那麼 j 的值是 3。code
假設執行順序是 1 -> 2 -> 3:那麼 j 的值是 2。
若咱們想要按照 1 ,2 ,3順序執行。那麼只有同步才能保證一致性。
總而言之:
經過JMM內存模型,volatile 內存可見性的實現才得以保證。可是又不須要咱們去關注不一樣平臺的細節。當對一個 volatile 修飾的變量修改是,JMM 會把該線程對應的本地內存中的共享變量刷新到主內存中。
當讀一個 volatile 變量的時候, JMM 會把該線程對應的本地內存設置無效,並從主內存中讀取共享變量。
volatile 在知足 Happens-before原則狀況下,禁止指令重排序。
親愛的讀者朋友以爲文章不錯點贊或關注公衆號將是我最大的支持。歡迎關注公衆號獲取最新技術文章。