您好,登錄后才能下訂單哦!
Java中內(nèi)存模型的原理是什么,很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來(lái)學(xué)習(xí)下,希望你能有所收獲。
語(yǔ)義規(guī)范
Java編程語(yǔ)言的語(yǔ)義允許編譯器和微處理器執(zhí)行優(yōu)化,從而與不正確同步的代碼進(jìn)行交互來(lái)完成工作.
線(xiàn)程內(nèi)語(yǔ)義是單線(xiàn)程程序的語(yǔ)義,它允許根據(jù)線(xiàn)程內(nèi)讀操作看到的值來(lái)完全預(yù)測(cè)線(xiàn)程的行為;由于單線(xiàn)程內(nèi)的實(shí)現(xiàn)是在其上下文執(zhí)行的, 可以通過(guò)評(píng)估線(xiàn)程的實(shí)現(xiàn)從而確定執(zhí)行中的線(xiàn)程的操作是否合法.
程序遵循線(xiàn)程內(nèi)語(yǔ)義: 在線(xiàn)程隔離狀態(tài)下,每個(gè)線(xiàn)程的操作必須由該線(xiàn)程的語(yǔ)義控制,但是每個(gè)讀操作看到的值由內(nèi)存模型決定.
JMM規(guī)范
從數(shù)據(jù)存儲(chǔ)上,對(duì)于共享數(shù)據(jù)的讀寫(xiě)操作,JMM會(huì)通過(guò)線(xiàn)程工作內(nèi)存以及JVM的堆內(nèi)存來(lái)對(duì)數(shù)據(jù)進(jìn)行讀寫(xiě)操作(類(lèi)比互聯(lián)網(wǎng)業(yè)務(wù),工作內(nèi)存類(lèi)比為redis等緩存,堆內(nèi)存類(lèi)比為數(shù)據(jù)儲(chǔ)存載體,如數(shù)據(jù)庫(kù))
從代碼優(yōu)化上,JMM為了提升性能,會(huì)針對(duì)程序順序代碼進(jìn)行重排序甚至刪除不必要的同步代碼
JMM概要
給定程序以及一個(gè)檢測(cè)程序是否合法的執(zhí)行跟蹤,JMM工作原理是檢查執(zhí)行跟蹤中的每個(gè)讀,并根據(jù)某些規(guī)則檢查讀觀(guān)察到的寫(xiě)是否有效
主要保證執(zhí)行的每個(gè)結(jié)果與內(nèi)存模型預(yù)期值一致,那么它可以不關(guān)心實(shí)現(xiàn)者是如何實(shí)現(xiàn)程序的行為
內(nèi)存模型決定在程序的每個(gè)點(diǎn)可以讀取哪些值。在隔離狀態(tài)下,每個(gè)線(xiàn)程的操作必須由該線(xiàn)程的語(yǔ)義控制,但是每個(gè)讀操作看到的值由內(nèi)存模型決定
每次在線(xiàn)程內(nèi)對(duì)變量進(jìn)行寫(xiě)行為產(chǎn)生一個(gè)線(xiàn)程間的動(dòng)作時(shí),它必須匹配程序順序中緊隨其后的讀行為的線(xiàn)程間動(dòng)作,其中對(duì)于線(xiàn)程的讀操作行為獲取的值是由于JMM決定的值
程序順序與順序一致性
程序順序
可描述為線(xiàn)程間所有動(dòng)作是根據(jù)線(xiàn)程內(nèi)語(yǔ)義執(zhí)行操作順序的一個(gè)集合
簡(jiǎn)言之,就是在線(xiàn)程內(nèi)的操作所見(jiàn)即所得,即程序代碼順序
順序一致性?xún)?nèi)存模型
一個(gè)線(xiàn)程所有操作都必須按照程序的順序來(lái)執(zhí)行
不論線(xiàn)程是否同步,所有線(xiàn)程都只能看到一個(gè)單一的操作執(zhí)行順序,并且每個(gè)操作都必須是原子性操作并立即對(duì)其他所有線(xiàn)程可見(jiàn)
順序一致性問(wèn)題
如果內(nèi)存模型使用一致性模型,則將會(huì)導(dǎo)致編譯器和處理器的優(yōu)化策略變得不合法
JMM在順序一致性方面的努力
源代碼
// shared.java
int pwrite = 0;
int cwrite = 0;
// producer.java
int pread = 0;
int r1 = 0;
run(){
r1 = 20; // --- 1
pread = cwrite; // --- 2
pwrite = 10; // --- 3
}
// consumer.java
int cread = 0;
int r2 = 0;
run(){
cread = pwrite; // --- 4
r2 = 21; // --- 5
cwrite = 20; // --- 6
}
代碼分析
基于JMM模型: 由于存在數(shù)據(jù)競(jìng)爭(zhēng),上面的代碼執(zhí)行順序會(huì)在編譯器階段,JMM允許對(duì)程序代碼進(jìn)行重排序,輸出結(jié)果會(huì)出現(xiàn)pread = cwrite = 20 與 cread = pwrite = 10的情況
基于一致性?xún)?nèi)存模型: 將會(huì)正常輸出,不會(huì)出現(xiàn)pread = cwrite = 20 與 cread = pwrite = 10的情況,但是線(xiàn)程之間的順序會(huì)交替執(zhí)行
加鎖方案
基于JMM模型: 保證輸出結(jié)果的正常,但是在上述線(xiàn)程內(nèi)執(zhí)行的順序會(huì)被重排序
一致性?xún)?nèi)存模型: 不會(huì)打亂順序,仍然正常結(jié)果輸出
小結(jié)
在存在數(shù)據(jù)競(jìng)爭(zhēng)的條件下,JMM無(wú)法保證線(xiàn)程之間的執(zhí)行順序,而順序一致性保證與代碼執(zhí)行的順序相同,即使線(xiàn)程的執(zhí)行順序存在交替執(zhí)行也不影響單個(gè)線(xiàn)程內(nèi)的執(zhí)行順序
單個(gè)線(xiàn)程中,JMM仍然會(huì)對(duì)臨界區(qū)的執(zhí)行動(dòng)作進(jìn)行重排序,而順序一致性并沒(méi)有進(jìn)行重排,仍然保持與程序代碼相同的順序
共享數(shù)據(jù)規(guī)則
能夠被多個(gè)線(xiàn)程共享的內(nèi)存區(qū)域稱(chēng)為共享內(nèi)存或是堆內(nèi)存
線(xiàn)程共享數(shù)據(jù): 所有的對(duì)象實(shí)例字段,static字段,數(shù)組元素等
線(xiàn)程封閉數(shù)據(jù): 局部變量,方法參數(shù),異常處理器以及ThreadLocal/ThreadLocalRandom等
線(xiàn)程操作規(guī)則
相當(dāng)于線(xiàn)程行為可以被其他線(xiàn)程看到,也可以檢測(cè)到其他線(xiàn)程的行為動(dòng)作,程序行為表現(xiàn)如下:
可以執(zhí)行正常的讀操作
可以執(zhí)行正常的寫(xiě)操作
對(duì)于同步代碼塊
可以執(zhí)行volatile數(shù)據(jù)的讀取,說(shuō)明其他線(xiàn)程的寫(xiě)操作當(dāng)前線(xiàn)程可以“看到”(寫(xiě)操作在線(xiàn)程失效直接讀取主內(nèi)存)
可以執(zhí)行volatile數(shù)據(jù)的寫(xiě),說(shuō)明變量數(shù)據(jù)可以對(duì)其他線(xiàn)程“可見(jiàn)”
lock鎖定監(jiān)視器
unlock解鎖監(jiān)視器
線(xiàn)程合并執(zhí)行的第一個(gè)和最后一個(gè)動(dòng)作(個(gè)人理解為等待多個(gè)線(xiàn)程執(zhí)行子任務(wù)之后再一同執(zhí)行程序后續(xù)代碼的場(chǎng)景)
啟動(dòng)線(xiàn)程和終止線(xiàn)程
Synchronization原則(能夠被感知,可見(jiàn)行為的變化)
監(jiān)視器m的解鎖與監(jiān)視器m的后續(xù)動(dòng)作加鎖操作同步
線(xiàn)程對(duì)volatile變量v進(jìn)行寫(xiě)操作,與任何線(xiàn)程對(duì)v的所有后續(xù)讀操作同步
啟動(dòng)線(xiàn)程的操作與線(xiàn)程執(zhí)行的第一個(gè)動(dòng)作的操作同步
在線(xiàn)程中對(duì)每個(gè)屬性執(zhí)行默認(rèn)值的寫(xiě)入操作與線(xiàn)程的第一個(gè)動(dòng)作操作同步
線(xiàn)程中的最終動(dòng)作T1 與另一個(gè)線(xiàn)程T2中檢測(cè)到T1已終止的任何動(dòng)作同步
如果線(xiàn)程T1中斷thread T2,則該中斷線(xiàn)程T1 將與 任何其他線(xiàn)程(包括T2)確定T2已被中斷(通過(guò)InterruptedException引發(fā)或調(diào)用Thread.interrupted 或Thread.isInterrupted)的任何點(diǎn)同步
Happen-Before原則(規(guī)范)
執(zhí)行動(dòng)作之間的happen-before關(guān)系
如果兩個(gè)動(dòng)作x和y,我們定義hb(x,y)來(lái)描述x happen before y,滿(mǎn)足關(guān)系有以下情況:
同一個(gè)線(xiàn)程中執(zhí)行動(dòng)作x和y,在程序順序上x(chóng)優(yōu)先于y,則hb(x,y)
對(duì)象構(gòu)造器代碼塊的結(jié)束happen-before該對(duì)象finalizer的開(kāi)始
如果x動(dòng)作與接下來(lái)的y動(dòng)作同步,則hb(x,y)
傳遞性,如果hb(x,y),且hb(y,z),則hb(x,z)
happen-before原則
主要作用于兩個(gè)的動(dòng)作存在沖突的執(zhí)行順序以及定義數(shù)據(jù)競(jìng)爭(zhēng)發(fā)生的時(shí)機(jī),具體VM實(shí)現(xiàn),遵循以下原則:
線(xiàn)程解鎖動(dòng)作都happen-before該線(xiàn)程的后續(xù)動(dòng)作鎖操作
對(duì)volatile變量執(zhí)行寫(xiě)操作happen-before該變量讀操作的后續(xù)每個(gè)動(dòng)作
調(diào)用線(xiàn)程的start()方法happen-before于已開(kāi)啟的線(xiàn)程內(nèi)的任何一個(gè)動(dòng)作
線(xiàn)程所有動(dòng)作happen-before于其他任意線(xiàn)程成功從該線(xiàn)程對(duì)象的join()方法返回
程序任何對(duì)象的初始化happen-before于程序中任何其他的動(dòng)作操作行為
作用
遵循上述的原則,意味著有些代碼不能進(jìn)行重排序,有些數(shù)據(jù)不能被緩存(解決JMM可見(jiàn)性的規(guī)范)
看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝您對(duì)億速云的支持。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。