最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java內(nèi)存模型及其作用詳解

 更新時(shí)間:2024年04月03日 10:45:24   作者:牽著貓散步的鼠鼠  
在現(xiàn)代計(jì)算機(jī)系統(tǒng)中,尤其是多處理器架構(gòu)下,每個(gè)處理器都有自己的高速緩存,而主內(nèi)存(RAM)是所有處理器共享的數(shù)據(jù)存儲(chǔ)區(qū)域,這篇文章主要介紹了深入理解Java內(nèi)存模型及其作用,需要的朋友可以參考下

1.前言

當(dāng)問(wèn)到 Java 內(nèi)存模型的時(shí)候,一定要注意,Java 內(nèi)存模型(Java Memory Model,JMM)它和 JVM 內(nèi)存布局(JVM 運(yùn)行時(shí)數(shù)據(jù)區(qū)域)是不一樣的,它們是兩個(gè)完全不同的概念。

2.為什么要有 Java 內(nèi)存模型?

Java 內(nèi)存模型存在的原因在于解決多線程環(huán)境下并發(fā)執(zhí)行時(shí)的內(nèi)存可見(jiàn)性和一致性問(wèn)題。在現(xiàn)代計(jì)算機(jī)系統(tǒng)中,尤其是多處理器架構(gòu)下,每個(gè)處理器都有自己的高速緩存,而主內(nèi)存(RAM)是所有處理器共享的數(shù)據(jù)存儲(chǔ)區(qū)域。當(dāng)多個(gè)線程同時(shí)訪問(wèn)和修改同一塊共享數(shù)據(jù)時(shí),如果沒(méi)有適當(dāng)?shù)耐綑C(jī)制,就可能導(dǎo)致以下問(wèn)題:

  • 可見(jiàn)性:一個(gè)線程對(duì)共享變量所做的修改可能不會(huì)立即反映到另一個(gè)線程的視角中,因?yàn)檫@些修改可能只存在于本地緩存中,并未刷新回主內(nèi)存。
  • 有序性:編譯器和處理器為了優(yōu)化性能,可能會(huì)對(duì)指令進(jìn)行重排序,這可能導(dǎo)致程序在單線程環(huán)境中看似按照源代碼順序執(zhí)行,但在多線程環(huán)境中的實(shí)際執(zhí)行順序卻與預(yù)期不同。
  • 原子性:即使是最簡(jiǎn)單的讀取或賦值操作,在硬件層面也不一定保證是原子性的,即在沒(méi)有同步的情況下,多線程下可能看到操作只執(zhí)行了一部分的結(jié)果。

Java 內(nèi)存模型通過(guò)定義一套規(guī)則來(lái)規(guī)范并限制編譯器、運(yùn)行時(shí)以及處理器對(duì)內(nèi)存訪問(wèn)的重排序行為,確保了多線程間的交互具有明確的語(yǔ)義。它規(guī)定了共享變量的訪問(wèn)規(guī)則、提供了 happens-before 原則以及 volatile 關(guān)鍵字、synchronized 等工具來(lái)實(shí)現(xiàn)內(nèi)存可見(jiàn)性和一致性的保障。這樣,程序員在編寫(xiě)并發(fā)代碼時(shí),可以依據(jù)這些規(guī)則來(lái)確保代碼的正確執(zhí)行,從而避免由于多線程帶來(lái)的不確定性和錯(cuò)誤。

如果沒(méi)有 Java 內(nèi)存模型就會(huì)出現(xiàn)以下兩大問(wèn)題:

  • CPU 和 內(nèi)存一致性問(wèn)題。
  • 指令重排序問(wèn)題。

具體內(nèi)容如下。

2.1 一致性問(wèn)題

要講明白緩存一致性問(wèn)題,要從計(jì)算機(jī)的內(nèi)存結(jié)構(gòu)說(shuō)起,它的結(jié)構(gòu)是這樣的: 

 所以從上面可以看出計(jì)算機(jī)的重要組成部分包含以下內(nèi)容:

  • CPU
  • CPU 寄存器:也叫 L1 緩存,一級(jí)緩存。
  • CPU 高速緩存:也叫 L2 緩存,二級(jí)緩存。
  • (主)內(nèi)存

當(dāng)然,部分高端機(jī)器還有 L3 三級(jí)緩存。

由于主內(nèi)存與 CPU 處理器的運(yùn)算能力之間有數(shù)量級(jí)的差距,所以在傳統(tǒng)計(jì)算機(jī)內(nèi)存架構(gòu)中會(huì)引入高速緩存(L2)來(lái)作為主存和處理器之間的緩沖,CPU 將常用的數(shù)據(jù)放在高速緩存中,運(yùn)算結(jié)束后 CPU 再講運(yùn)算結(jié)果同步到主內(nèi)存中,這樣就會(huì)導(dǎo)致多個(gè)線程在進(jìn)行操作和同步時(shí),導(dǎo)致 CPU 緩存和主內(nèi)存數(shù)據(jù)不一致的問(wèn)題。

2.2 重排序問(wèn)題

由于有 JIT(Just In Time,即時(shí)編譯)技術(shù)的存在,它可能會(huì)對(duì)代碼進(jìn)行優(yōu)化,比如將原本執(zhí)行順序?yàn)?a -> b -> c 的流程,“優(yōu)化”成 a -> c -> b 了,但這樣優(yōu)化之后,可能會(huì)導(dǎo)致我們的程序在某些場(chǎng)景執(zhí)行出錯(cuò),比如單例模式雙重效驗(yàn)鎖的場(chǎng)景,這就是典型的好心辦壞事的事例。

3.Java 內(nèi)存模型的定義

Java 內(nèi)存模型(Java Memory Model,簡(jiǎn)稱(chēng) JMM)是一種規(guī)范,它定義了 Java 虛擬機(jī)(JVM)在計(jì)算機(jī)內(nèi)存(RAM)中的工作方式,即規(guī)范了 Java 虛擬機(jī)與計(jì)算機(jī)內(nèi)存之間是如何協(xié)同工作的。具體來(lái)說(shuō),它規(guī)定了一個(gè)線程如何和何時(shí)可以看到其他線程修改過(guò)的共享變量的值,以及在必須時(shí)如何同步地訪問(wèn)共享變量。

4.規(guī)范內(nèi)容

Java 內(nèi)存模型主要包括以下內(nèi)容:

  • 主內(nèi)存(Main Memory):所有線程共享的內(nèi)存區(qū)域,包含了對(duì)象的字段、方法和運(yùn)行時(shí)常量池等數(shù)據(jù)。
  • 工作內(nèi)存(Working Memory):每個(gè)線程擁有自己的工作內(nèi)存,用于存儲(chǔ)主內(nèi)存中的數(shù)據(jù)的副本,線程只能直接操作工作內(nèi)存中的數(shù)據(jù)。
  • 內(nèi)存間交互操作:線程通過(guò)讀取和寫(xiě)入操作與主內(nèi)存進(jìn)行交互。讀操作將數(shù)據(jù)從主內(nèi)存復(fù)制到工作內(nèi)存,寫(xiě)操作將修改后的數(shù)據(jù)刷新到主內(nèi)存。
  • 原子性(Atomicity):JMM 保證基本數(shù)據(jù)類(lèi)型(如 int、long)的讀寫(xiě)操作具有原子性,即不會(huì)被其他線程干擾,保證操作的完整性。
  • 可見(jiàn)性(Visibility):JMM 確保一個(gè)線程對(duì)共享變量的修改對(duì)其他線程可見(jiàn)。這意味著一個(gè)線程在工作內(nèi)存中修改了數(shù)據(jù)后,必須將最新的數(shù)據(jù)刷新到主內(nèi)存,以便其他線程可以讀取到更新后的數(shù)據(jù)。
  • 有序性(Ordering):JMM 保證程序的執(zhí)行順序按照一定的規(guī)則進(jìn)行,不會(huì)出現(xiàn)隨機(jī)的重排序現(xiàn)象。這包括了編譯器重排序、處理器重排序和內(nèi)存重排序等。

Java 內(nèi)存模型通過(guò)以上規(guī)則和語(yǔ)義,提供了一種統(tǒng)一的內(nèi)存訪問(wèn)方式,使得多線程程序的行為可預(yù)測(cè)、可理解,并幫助開(kāi)發(fā)者編寫(xiě)正確和高效的多線程代碼。開(kāi)發(fā)者可以利用 JMM 提供的同步機(jī)制(如關(guān)鍵字 volatile、synchronized、Lock 等)來(lái)實(shí)現(xiàn)線程之間的同步和通信,以確保線程安全和數(shù)據(jù)一致性。

內(nèi)存模型的簡(jiǎn)單執(zhí)行示例圖如下: 

4.1 主內(nèi)存和工作內(nèi)存交互規(guī)范

為了更好的控制主內(nèi)存和本地內(nèi)存的交互,Java 內(nèi)存模型定義了八種操作來(lái)實(shí)現(xiàn)(以下內(nèi)容只需要簡(jiǎn)單了解即可):

  • lock(鎖定):作用于主內(nèi)存的變量,把一個(gè)變量標(biāo)識(shí)為一條線程獨(dú)占狀態(tài)。
  • unlock(解鎖):作用于主內(nèi)存變量,把一個(gè)處于鎖定狀態(tài)的變量釋放出來(lái),釋放后的變量才可以被其他線程鎖定。
  • read(讀取):作用于主內(nèi)存變量,把一個(gè)變量值從主內(nèi)存?zhèn)鬏數(shù)骄€程的工作內(nèi)存中,以便隨后的 load 動(dòng)作使用
  • load(載入):作用于工作內(nèi)存的變量,它把 read 操作從主內(nèi)存中得到的變量值放入工作內(nèi)存的變量副本中。
  • use(使用):作用于工作內(nèi)存的變量,把工作內(nèi)存中的一個(gè)變量值傳遞給執(zhí)行引擎,每當(dāng)虛擬機(jī)遇到一個(gè)需要使用變量的值的字節(jié)碼指令時(shí)將會(huì)執(zhí)行這個(gè)操作。
  • assign(賦值):作用于工作內(nèi)存的變量,它把一個(gè)從執(zhí)行引擎接收到的值賦值給工作內(nèi)存的變量,每當(dāng)虛擬機(jī)遇到一個(gè)給變量賦值的字節(jié)碼指令時(shí)執(zhí)行這個(gè)操作。
  • store(存儲(chǔ)):作用于工作內(nèi)存的變量,把工作內(nèi)存中的一個(gè)變量的值傳送到主內(nèi)存中,以便隨后的write的操作。
  • write(寫(xiě)入):作用于主內(nèi)存的變量,它把 store 操作從工作內(nèi)存中一個(gè)變量的值傳送到主內(nèi)存的變量中。

PS:工作內(nèi)存也就是本地內(nèi)存的意思。

4.2 什么是 happens-before 原則?

happens-before(先行發(fā)生)原則是 Java 內(nèi)存模型中定義的用于保證多線程環(huán)境下操作執(zhí)行順序和可見(jiàn)性的一種重要手段。

舉個(gè)例子來(lái)說(shuō),例如 A happens-before B,也就是 A 線程早于 B 線程執(zhí)行,那么 A happens-before B 可以保障以下兩項(xiàng)內(nèi)容:

  • 可見(jiàn)性:B 讀取到 A 最新修改的值(通過(guò)內(nèi)存屏障)。
  • 順序性:編譯器優(yōu)化、處理器重排序等因素不會(huì)影響先執(zhí)行 A 再執(zhí)行 B 的順序。

到此這篇關(guān)于深入理解Java內(nèi)存模型及其作用的文章就介紹到這了,更多相關(guān)Java內(nèi)存模型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java之抽象類(lèi)和繼承抽象類(lèi)解讀

    java之抽象類(lèi)和繼承抽象類(lèi)解讀

    這篇文章主要介紹了java之抽象類(lèi)和繼承抽象類(lèi),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • 一文詳解如何查看jdk版本及安裝路徑

    一文詳解如何查看jdk版本及安裝路徑

    這篇文章主要給大家介紹了關(guān)于如何查看jdk版本及安裝路徑的相關(guān)資料,JDK是Java語(yǔ)言的軟件開(kāi)發(fā)工具包,主要用于移動(dòng)設(shè)備、嵌入式設(shè)備上的java應(yīng)用程序,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-10-10
  • SpringBoot結(jié)合JWT實(shí)現(xiàn)用戶(hù)登錄、注冊(cè)、鑒權(quán)

    SpringBoot結(jié)合JWT實(shí)現(xiàn)用戶(hù)登錄、注冊(cè)、鑒權(quán)

    用戶(hù)登錄、注冊(cè)及鑒權(quán)是我們基本所有系統(tǒng)必備的,也是很核心重要的一塊,本文主要介紹了SpringBoot結(jié)合JWT實(shí)現(xiàn)用戶(hù)登錄、注冊(cè)、鑒權(quán),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2023-05-05
  • 詳解SpringBoot?統(tǒng)一后端返回格式的方法

    詳解SpringBoot?統(tǒng)一后端返回格式的方法

    今天我們來(lái)聊一聊在基于SpringBoot前后端分離開(kāi)發(fā)模式下,如何友好的返回統(tǒng)一的標(biāo)準(zhǔn)格式以及如何優(yōu)雅的處理全局異常,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2022-05-05
  • java并發(fā)編程之進(jìn)程和線程調(diào)度基礎(chǔ)詳解

    java并發(fā)編程之進(jìn)程和線程調(diào)度基礎(chǔ)詳解

    這篇文章主要介紹了java并發(fā)編程之進(jìn)程和線程調(diào)度基礎(chǔ),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • IDEA報(bào)錯(cuò)“Command line is too long”的解決步驟

    IDEA報(bào)錯(cuò)“Command line is too long”的解決步驟

    這篇文章解釋了在使用SpringBoot項(xiàng)目時(shí),因啟動(dòng)命令行過(guò)長(zhǎng)導(dǎo)致啟動(dòng)失敗的問(wèn)題,并提供了兩種解決方案:JARmanifest和classpathfile,推薦使用JARmanifest,如果遇到類(lèi)加載問(wèn)題可;同時(shí)提供了修改默認(rèn)模板的方法,以避免以后的新項(xiàng)目再次遇到此問(wèn)題,需要的朋友可以參考下
    2026-05-05
  • Springboot+mybatis-plus+注解實(shí)現(xiàn)數(shù)據(jù)權(quán)限隔離

    Springboot+mybatis-plus+注解實(shí)現(xiàn)數(shù)據(jù)權(quán)限隔離

    本文將結(jié)合實(shí)例代碼,介紹Springboot+mybatis-plus+注解實(shí)現(xiàn)數(shù)據(jù)權(quán)限隔離,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-07-07
  • MyBatisPlus自定義SQL的實(shí)現(xiàn)

    MyBatisPlus自定義SQL的實(shí)現(xiàn)

    MyBatisPlus提供了自定義SQL功能,允許開(kāi)發(fā)者在Mapper接口中定義方法,并通過(guò)XML文件或注解編寫(xiě)SQL語(yǔ)句,本文詳解了如何在MP中使用自定義SQL,感興趣的可以了解一下
    2024-09-09
  • 基于Spring Security前后端分離的權(quán)限控制系統(tǒng)問(wèn)題

    基于Spring Security前后端分離的權(quán)限控制系統(tǒng)問(wèn)題

    本文給大家分享基于Spring Security前后端分離的權(quán)限控制系統(tǒng)問(wèn)題,需要了解權(quán)限如何加載,權(quán)限匹配規(guī)則和登錄的實(shí)現(xiàn)代碼,對(duì)Spring Security權(quán)限控制系統(tǒng)相關(guān)知識(shí)感興趣的朋友一起看看吧
    2021-06-06
  • 詳解Java數(shù)組的定義和聲明方法

    詳解Java數(shù)組的定義和聲明方法

    在Java開(kāi)發(fā)中,數(shù)組是最常用的數(shù)據(jù)結(jié)構(gòu)之一,因此,深入了解Java數(shù)組的定義和聲明是非常必要的,本文將詳細(xì)介紹Java數(shù)組的定義和聲明方法,以及其在實(shí)際開(kāi)發(fā)中的應(yīng)用場(chǎng)景、優(yōu)缺點(diǎn)等方面,需要的朋友可以參考下
    2023-11-11

最新評(píng)論

岢岚县| 吕梁市| 鄂托克旗| 万源市| 东乡县| 永善县| 民县| 阿拉善右旗| 岱山县| 固镇县| 石狮市| 巢湖市| 九台市| 万宁市| 江西省| 余干县| 崇礼县| 庆城县| 千阳县| 自治县| 德昌县| 万源市| 德化县| 拜城县| 桐梓县| 那坡县| 尼木县| 电白县| 界首市| 旺苍县| 芜湖县| 海南省| 曲沃县| 即墨市| 布拖县| 晋中市| 南乐县| 东城区| 揭阳市| 图们市| 会昌县|