1. 程式人生 > 其它 >【面試題】你知道指令重排以及happens-before原則是什麼嗎?

【面試題】你知道指令重排以及happens-before原則是什麼嗎?

技術標籤: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、一個執行緒內的所有程式碼是按順序執行的(單執行緒中的指令重排,不影響結果)。只有多執行緒中,才存在指令重排的問題(多執行緒問題本質上是共享變數的問題)