掌握好這些Java內存模型知識,你才算一個合格的程序員!

小編的話

在文章的開始作者為大家整理了很多資料!包括一線大廠Java面試題總結+各知識點學習思維導+一份300頁pdf文檔的Java核心知識點總結! 這些資料的內容都是面試時面試官必問的知識點,篇章包括了很多知識點,其中包括了有基礎知識、Java集合、JVM、多線程并發(fā)、spring原理、微服務、Netty 與RPC 、Kafka、日記、設計模式、Java算法、數據庫、Zookeeper、分布式緩存、數據結構等等。


你要是需要的話點這里直接下載就好了,希望對你有幫助

Java內存模型

簡單介紹一下Java內存模型

Java內存模型即Java Memory Model,簡稱JMM。JMM定義了Java 虛擬機(JVM)在計算機內存(RAM)中的工作方式。JVM是整個計算機虛擬模型,所以JMM是隸屬于JVM的。

Java內存模型是共享內存的并發(fā)模型,線程之間主要通過讀-寫共享變量(堆內存中的實例域,靜態(tài)域和數組元素)來完成隱式通信。Java 內存模型(JMM)控制 Java 線程之間的通信,決定一個線程對共享變量的寫入何時對另一個線程可見。

JVM主內存與工作內存

Java 內存模型的主要目標是定義程序中各個變量的訪問規(guī)則,即在虛擬機中將變量(線程共享的變量)存儲到內存和從內存中取出變量這樣底層細節(jié)。

Java內存模型中規(guī)定了所有的變量都存儲在主內存中,每條線程還有自己的工作內存,線程對變量的所有操作都必須在工作內存中進行,而不能直接讀寫主內存中的變量。這里的工作內存是 JMM 的一個抽象概念,也叫本地內存,其存儲了該線程以讀 / 寫共享變量的副本。

就像每個處理器內核擁有私有的高速緩存,JMM 中每個線程擁有私有的本地內存。不同線程之間無法直接訪問對方工作內存中的變量,線程間的通信一般有兩種方式進行,一是通過消息傳遞,二是共享內存。Java 線程間的通信采用的是共享內存方式,線程、主內存和工作內存的交互關系如下圖所示:


線程A和線程B通信要經過兩個步驟:

線程A把本地內存A中更新過的共享變量刷新到主內存中
線程B到主內存中去讀取線程A之前已更新過的共享變量
這里所講的主內存、工作內存與 Java 內存區(qū)域中的 Java 堆、棧、方法區(qū)等并不是同一個層次的內存劃分,這兩者基本上是沒有關系的,如果兩者一定要勉強對應起來,那從變量、主內存、工作內存的定義來看,主內存主要對應于Java堆中的對象實例數據部分,而工作內存則對應于虛擬機棧中的部分區(qū)域。

JMM數據原子操作

read(讀?。簭闹鲀却孀x取數據
load(載入):將主內存讀取到的數據寫入工作內存
use(使用):從工作內存讀取數據來計算
assign(賦值):將計算好的值重新賦值到工作內存中
store(存儲):將工作內存數據寫入主內存
write(寫入):將store過去的變量值賦值給主內存中的變量
lock(鎖定):將主內存變量加鎖,標識為線程獨占狀態(tài)
unlock(解鎖):將主內存變量解鎖,解鎖后其他線程可以鎖定該變量

public class VolatileVisibilityTest {

    private static volatile boolean initFlag = false;

    public static void main(String[] args) throws InterruptedException {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("waiting data...");
                while (!initFlag) {
                }
                System.out.println("====================success");
            }
        }).start();

        Thread.sleep(2000);

        new Thread(new Runnable() {
            @Override
            public void run() {
                prepareDate();
            }
        }).start();
    }

    public static void prepareDate() {
        System.out.println("preparing data...");
        initFlag = true;
        System.out.println("prepare end...");
    }
}


計算機高速緩存和緩存一致性

計算機在高速的 CPU 和相對低速的存儲設備之間使用高速緩存,作為內存和處理器之間的緩沖。將運算需要使用到的數據復制到緩存中,讓運算能快速運行,當運算結束后再從緩存同步回內存之中。

在多處理器的系統中(或者單處理器多核的系統),每個處理器內核都有自己的高速緩存,它們有共享同一主內存(Main Memory)。當多個處理器的運算任務都涉及同一塊主內存區(qū)域時,將可能導致各自的緩存數據不一致。

為此,需要各個處理器訪問緩存時都遵循一些協議,在讀寫時要根據協議進行操作,來維護緩存的一致性。

MESI緩存一致性協議:多個CPU從主存讀取同一個數據到各自的告訴緩存,當其中某個CPU修改了緩存里的數據,該數據會馬上同步會主內存,其他CPU通過總線嗅探機制可以感知到數據的變化從而將自己緩存里的數據失效。



volatile緩存可見性實現原理

底層實現主要通過匯編lock前綴指令,它會鎖定這塊內存區(qū)域的緩存(緩存行鎖定)并回寫到主存

1)會將當前處理器緩存行的數據立即寫回到系統內存
2)這個寫回內存的操作會引起在其他CPU里緩存了該內存地址的數據無效(MESI)

重排序和happens-before規(guī)則

在執(zhí)行程序時為了提高性能,編譯器和處理器常常會對指令做重排序。重排序分三種類型:

編譯器優(yōu)化的重排序。編譯器在不改變單線程程序語義的前提下,可以重新安排語句的執(zhí)行順序。
指令級并行的重排序?,F代處理器采用了指令級并行技術(Instruction-Level Parallelism, ILP)來將多條指令重疊執(zhí)行。如果不存在數據依賴性,處理器可以改變語句對應機器指令的執(zhí)行順序。
內存系統的重排序。由于處理器使用緩存和讀 / 寫緩沖區(qū),這使得加載和存儲操作看上去可能是在亂序執(zhí)行。
從 java 源代碼到最終實際執(zhí)行的指令序列,會分別經歷下面三種重排序:

JMM 屬于語言級的內存模型,它確保在不同的編譯器和不同的處理器平臺之上,通過禁止特定類型的編譯器重排序和處理器重排序,為程序員提供一致的內存可見性保證。java 編譯器禁止處理器重排序是通過在生成指令序列的適當位置會插入內存屏障(重排序時不能把后面的指令重排序到內存屏障之前的位置)指令來實現的。

happens-before

從 JDK5 開始,java 內存模型提出了 happens-before 的概念,通過這個概念來闡述操作之間的內存可見性。如果一個操作執(zhí)行的結果需要對另一個操作可見,那么這兩個操作之間必須存在 happens-before 關系。這里提到的兩個操作既可以是在一個線程之內,也可以是在不同線程之間。這里的“可見性”是指當一條線程修改了這個變量的值,新值對于其他線程來說是可以立即得知的。

如果 A happens-before B,那么 Java 內存模型將向程序員保證—— A 操作的結果將對 B 可見,且 A 的執(zhí)行順序排在 B 之前。

重要的 happens-before 規(guī)則如下:

程序順序規(guī)則:一個線程中的每個操作,happens- before 于該線程中的任意后續(xù)操作。
監(jiān)視器鎖規(guī)則:對一個監(jiān)視器鎖的解鎖,happens- before 于隨后對這個監(jiān)視器鎖的加鎖。
volatile 變量規(guī)則:對一個 volatile 域的寫,happens- before 于任意后續(xù)對這個 volatile 域的讀。
傳遞性:如果 A happens- before B,且 B happens- before C,那么 A happens- before C。
下圖是 happens-before 與 JMM 的關系

最后

在文章的最后作者為大家整理了很多資料!包括一線大廠Java面試題總結+各知識點學習思維導+一份300頁pdf文檔的Java核心知識點總結! 這些資料的內容都是面試時面試官必問的知識點,篇章包括了很多知識點,其中包括了有基礎知識、Java集合、JVM、多線程并發(fā)、spring原理、微服務、Netty 與RPC 、Kafka、日記、設計模式、Java算法、數據庫、Zookeeper、分布式緩存、數據結構等等。
歡迎關注公眾號:前程有光,領??!

?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容