【面試題】你知道指令重排以及happens-before原則是什麼嗎?
阿新 • • 發佈:2020-12-10
技術標籤:JVM
happens-before原則,一定程度上避免指令重排
編譯器、指令器可能對程式碼重排序、亂排、要守一定的規則,happens-before原則。只要符合happens-before的原則,那麼就不能胡亂重排序,如果不符合這個規則,那麼就可以自己排序。
happens-before八大原則
- 單執行緒happen-before原則:在同一個執行緒中,書寫在前面的操作happen-before後面的操作。
- 鎖的happen-before原則:同一個鎖的unlock操作happen-before此鎖的lock操作。
- volatile的happen-before原則:對一個volatile變數的寫操作happen-before對此變數的任意操作(當然也包括寫操作了)。
- happen-before的傳遞性原則:如果A操作 happen-before B操作,B操作happen-before C操作,那麼A操作happen-before C操作。
- 執行緒啟動的happen-before原則:同一個執行緒的start方法happen-before此執行緒的其它方法。
- 執行緒中斷的happen-before原則:對執行緒interrupt方法的呼叫happen-before被中斷執行緒的檢測到中斷髮送的程式碼。
- 執行緒終結的happen-before原則:執行緒中的所有操作都happen-before執行緒的終止檢測。
- 物件建立的happen-before原則:一個物件的初始化完成先於他的finalize方法呼叫。
有過有面試官問happens-before原則,不是說要把8條背出來。而是說,規則制定了在一些特殊情況下,不允許編譯器、指令器對你寫的程式碼進行指令重排,必須保證你的程式碼的有序性
但是如果沒有滿足上面的規則,那麼就可能會出現指令重排。這8條原則是避免出現指令重排的情況,要求這幾個重要的場景下,是按照順序來,但是8條規則之外,可以隨意重排指令。
flag = false;
//執行緒1
prepare();//準備資源
flag = true;
//執行緒2
while(flag){
Thread.sleep(1000);
}
execute();//基於準備好的資源執行操作
比如說這個例子,如果用volatile來修飾flag變數,一定可以讓prepare()指令在flag=true之前執行這就禁止了指令重排。因為volatile要求的是,volatile前面的程式碼一定不能指令重拍到其修飾的變數操作後面,volatile後面的程式碼也不能指令重排到volatile前面。
(1)知道指令重排是什麼意思
(2)知道happen-before原則
(3)volatile避免指令重排
【評論區】
1、一個執行緒內的所有程式碼是按順序執行的(單執行緒中的指令重排,不影響結果)。只有多執行緒中,才存在指令重排的問題(多執行緒問題本質上是共享變數的問題)