java內存模型 JMM
583
2025-04-01
happens-before
在JMM中,如果一個操作執行的結果需要對另一個操作可見,那么這兩個操作之間必須要存在happens-before關系。這里提到的兩個操作既可以是在一個線程之
內,也可以是在不同線程之間。
程序順序規則:一個線程中的每個操作,happens-before于該線程中的任意后續操作。
監視器鎖規則:對一個鎖的解鎖,happens-before于隨后對這個鎖的加鎖。
volatile變量規則:對一個volatile域的寫,happens-before于任意后續對這個volatile域的讀。
傳遞性:如果A happens-before B,且B happens-before C,那么A happens-before C。
兩個操作之間具有happens-before關系,并不意味著前一個操作必須要在后一個操作之前執行!happens-before僅僅要求前一個操作(執行的結果)對后一個操作
可見,且前一個操作按順序排在第二個操作之前(the first is visible to and ordered before the second)。
重排序
as-if-serial語義的意思是:不管怎么重排序(編譯器和處理器為了提高并行度),(單線程)程序的執行結果不能被改變。編譯器、runtime和處理器都必須遵守as-if-serial語義。
public class ReorderExample { int a = 0; volatile boolean flag = false; public void writer() { a = 2; // 1 } public void reader() { if (flag) { // 3 int i = a * a; // 4 System.out.println(i); } } }
假設有兩個線程A和B,A首先執行writer()方法,隨后B線程接著執行reader()方法。線程B在執行操作4時,能否看到線程A在操作1對共享變量a的寫入呢?
答案是:不一定能看到。
操作1和操作2做了重排序。程序執行時,線程A首先寫標記變量flag,隨后線程B讀這個變量。由于條件判斷為真,線程B將讀取變量a。此時,變量a還沒有被線程A寫入,在這里多線程程序的語義被重排序破壞了!
操作3和操作4存在控制依賴關系。當代碼中存在控制依賴性時,會影響指令序列執行的并行度。為此,編譯器和處理器會采用猜測(Speculation)執行來克服控制相關性對并行度的影響。以處理器的猜測執行為例,執行線程B的處理器可以提前讀取并計算a*a,然后把計算結果臨時保存到一個名為重排序緩沖(Reorder Buffer,ROB)的硬件緩存中。當操作3的條件判斷為真時,就把該計算結果寫入變量i中。
對操作3和4做了重排序。重排序在這里破壞了多線程程序的語義!
在單線程程序中,對存在控制依賴的操作重排序,不會改變執行結果(這也是as-if-serial語義允許對存在控制依賴的操作做重排序的原因);但在多線程程序中,對存在控制依賴的操作重排序,可能會改變程序的執行結果
Java 任務調度
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。