亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

什么是Java內存模型

發布時間:2021-06-28 16:50:39 來源:億速云 閱讀:251 作者:chen 欄目:編程語言

這篇文章主要講解了“什么是Java內存模型”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“什么是Java內存模型”吧!

前言

Java并發編程系列開坑了,Java并發編程可以說是中高級研發工程師的必備素養,也是中高級崗位面試必問的問題,本系列就是為了帶讀者們系統的一步一步擊破Java并發編程各個難點,打破屏障,在面試中所向披靡,拿到心儀的offer,Java并發編程系列文章依然采用圖文并茂的風格,讓小白也能秒懂。

Java內存模型(Java Memory Model)簡稱J M M,作為Java并發編程系列的開篇,它是Java并發編程的基礎知識,理解它能讓你更好的明白線程安全到底是怎么一回事

內容大綱

什么是Java內存模型

硬件內存模型

程序是指令與數據的集合,計算機執行程序時,是C P U在執行每條指令,因為C P U要從內存讀指令,又要根據指令指示去內存讀寫數據做運算,所以執行指令就免不了與內存打交道,早期內存讀寫速度與C P U處理速度差距不大,倒沒什么問題。

C P U緩存

隨著C P U技術快速發展,C P U的速度越來越快,內存卻沒有太大的變化,導致內存的讀寫(IO)速度與C P U的處理速度差距越來越大,為了解決這個問題,引入了緩存(Cache)的設計,在C P U與內存之間加上緩存層,這里的緩存層就是指C P U內的寄存器與高速緩存L1,L2,L3

什么是Java內存模型

上圖可以看出,C P U基本都是在和緩存層打交道,采用緩存設計彌補主存與C P U處理速度的差距,這種設計不僅僅體現在硬件層面,在日常開發中,那些并發量高的業務場景都能看到,但是凡事都有利弊,緩存雖然加快了速度,同樣也帶來了在多線程場景存在的緩存一致性問題,關于緩存一致性問題后面會說,這里大家留個印象。

Java內存模型

Java內存模型(Java Memory Model,J M M),后續都以J M M簡稱,J M M 是建立在硬件內存模型基礎上的抽象模型,并不是物理上的內存劃分,簡單說,為了使Java虛擬機(Java Virtual Machine,J V M)在各平臺下達到一致的內存交互效果,需要屏蔽下游不同硬件模型的交互差異,統一規范,為上游提供統一的使用接口。

J M M是保證J V M在各平臺下對計算機內存的交互都能保證效果一致的機制及規范

什么是Java內存模型

不難發現J M M與硬件內存模型差別不大,可以簡單的把線程類比成Core核心線程本地緩存類比成緩存層,如下圖所示

什么是Java內存模型

線程A執行流程

  • 線程A從緩存獲取變量a

  • 緩存未命中,從主存復制到緩存,此時a0

  • 線程A獲取變量a,執行計算

  • 計算結果1,寫入緩存

  • 計算結果1,寫入主存

線程B執行流程

  • 線程B從緩存獲取變量a

  • 緩存未命中,從主存復制到緩存,此時a1

  • 線程B獲取變量a,執行計算

  • 計算結果2,寫入緩存

  • 計算結果2,寫入主存

AB兩個線程執行完后,線程A與線程B緩存數據不一致,這就是緩存一致性問題,一個是1,另一個是2,如果線程A再進行一次+1操作,寫入主存的還是2,也就是說兩個線程對a共進行了3+1,期望的結果是3,最終得到的結果卻是2

解決緩存一致性問題,就要保證可見性,思路也很簡單,變量寫入主存后,把其他線程緩存的該變量清空,這樣其他線程緩存未命中,就會去主存加載。

線程A執行流程

  • 線程A從緩存獲取變量a

  • 緩存未命中,從主存復制到緩存,此時a0

  • 線程A獲取變量a,執行計算

  • 計算結果1,寫入緩存

  • 計算結果1,寫入主存,并清空線程B緩存a變量

線程B執行流程

  • 線程B從緩存獲取變量a

  • 緩存未命中,從主存復制到緩存,此時a1

  • 線程B獲取變量a,執行計算

  • 計算結果2,寫入緩存

  • 計算結果2,寫入主存,并清空線程A緩存a變量

AB兩個線程執行完后,線程A緩存是空的,此時線程A再進行一次+1操作,會從主存加載(先從緩存中獲取,緩存未命中,再從主存復制到緩存)得到2,最后寫入主存的是3Java中提供了volatile修飾變量保證可見性(本文重點是J M M,所以不會對volatile做過多的解讀)。

看似問題都解決了,然而上面描述的場景是建立在理想情況(線程有序的執行),實際中線程可能是并發(交替執行),也可能是并行,只保證可見性仍然會有問題,所以還需要保證原子性

原子性

原子性是指一個或者多個操作在C P U執行的過程中不被中斷的特性,要么執行,要不執行,不能執行到一半,為了直觀的了解什么是原子性,看看下面這段代碼

int a=0;
a++;
  • 原子性操作:int a=0只有一步操作,就是賦值

  • 非原子操作:a++有三步操作,讀取值、計算、賦值

如果多線程場景進行a++操作,僅保證可見性,沒有保證原子性,同樣會出現問題。

什么是Java內存模型

并發場景(線程交替執行)

  • 線程A讀取變量a到緩存,a0

  • 進行+1運算得到結果1

  • 切換到B線程

  • B線程執行完整個流程,a=1寫入主存

  • 線程A恢復執行,把結果a=1寫入緩存與主存

  • 最終結果錯誤

并行場(線程同時執行)

  • 線程A與線程B同時執行,可能線程A執行運算+1的時候,線程B就已經全部執行完成,也可能兩個線程同時計算完,同時寫入,不管是那種,結果都是錯誤的。

為了解決此問題,只要把多個操作變成一步操作,即保證原子性

什么是Java內存模型

并發場景(線程A與線程B交替執行)

  • 線程A獲取鎖成功

  • 線程A讀取變量a到緩存,進行+1運算得到結果1

  • 此時切換到了B線程

  • 線程B獲取鎖失敗,阻塞等待

  • 切換回線程A

  • 線程A執行完所有流程,主存a=1

  • 線程A釋放鎖成功,通知線程B獲取鎖

  • 線程B獲取鎖成功,讀取變量a到緩存,此時a=1

  • 線程B執行完所有流程,主存a=2

  • 線程B釋放鎖成功

并行場景

  • 線程A獲取鎖成功

  • 線程B獲取鎖失敗,阻塞等待

  • 線程A讀取變量a到緩存,進行+1運算得到結果1

  • 線程A執行完所有流程,主存a=1

  • 線程A釋放鎖成功,通知線程B獲取鎖

  • 線程B獲取鎖成功,讀取變量a到緩存,此時a=1

  • 線程B執行完所有流程,主存a=2

  • 線程B釋放鎖成功

synchronized對共享資源代碼段上鎖,達到互斥效果,天然的解決了無法保證原子性、可見性、有序性帶來的問題。

雖然在并行場A線程還是被中斷了,切換到了B線程,但它依然需要等待A線程執行完畢,才能繼續,所以結果的原子性得到了保證。

有序性

在日常搬磚寫代碼時,可能大家都以為,程序運行時就是按照編寫順序執行的,但實際上不是這樣,編譯器和處理器為了優化性能,會對代碼做重排,所以語句實際執行的先后順序與輸入的代碼順序可能一致,這就是指令重排序

可能讀者們會有疑問“指令重排為什么能優化性能?”,其實C P U會對重排后的指令做并行執行,達到優化性能的效果。

重排序前的指令

什么是Java內存模型

重排序后,對a操作的指令發生了改變,節省了一次Load aStore a,達到性能優化效果,這就是重排序帶來的好處。

重排遵循as-if-serial原則,編譯器和處理器不會對存在數據依賴關系的操作做重排序,因為這種重排序會改變執行結果(即不管怎么重排序,單線程程序的執行結果不能被改變),下面這種情況,就屬于數據依賴。

int i = 10int j = 10//這就是數據依賴,int i 與 int j 不能排到 int c下面去int c = i + j

但也僅僅只是針對單線程,多線程場景可沒這種保證,假設A、B兩個線程,線程A代碼段無數據依賴,線程B依賴線程A的結果,如下圖(假設保證了可見性

禁止重排場景(i默認0)

  • 線程A執行i = 10

  • 線程A執行b = true

  • 線程B執行if( b )通過驗證

  • 線程B執行i = i + 10

  • 最終結果i20

重排場景(i默認0)

  • 線程A執行b = true

  • 線程B執行if( b )通過驗證

  • 線程B執行i = i + 10

  • 線程A執行i = 10

  • 最終結果i10

為解決重排序,使用Java提供的volatile修飾變量同時保證可見性、有序性,被volatile修飾的變量會加上內存屏障禁止排序(本文重點是J M M,所以不會對volatile做過多的解讀)。

三大特性的保證

特性volatilesynchronizedLockAtomic
可見性可以保證可以保證可以保證可以保證
原子性無法保證可以保證可以保證可以保證
有序性一定程度保證可以保證可以保證無法保證


感謝各位的閱讀,以上就是“什么是Java內存模型”的內容了,經過本文的學習后,相信大家對什么是Java內存模型這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

左贡县| 土默特左旗| 本溪市| 白山市| 张家口市| 苍溪县| 顺平县| 自治县| 广昌县| 萍乡市| 名山县| 奇台县| 即墨市| 邻水| 武汉市| 台前县| 洛川县| 同仁县| 多伦县| 巴彦县| 裕民县| 思茅市| 南宫市| 惠来县| 辽阳市| 即墨市| 兴城市| 文水县| 玛曲县| 台中县| 梁平县| 涟源市| 隆回县| 南投市| 武威市| 新安县| 屏东县| 福建省| 将乐县| 石城县| 玉溪市|