Java多執行緒之指令重排
阿新 • • 發佈:2020-10-12
為什麼需要指令重排
通常一條指令的執行可以簡單分為以下幾個步驟:
- 取指(都取指令) IF
- 譯碼和去暫存器運算元 ID
- 執行或者有效地址計算 EX
- 儲存器訪問 MEM
- 寫回 WB
同樣的,彙編指令也不是一步就能執行完的,CPU實際工作時,需要分為多個步驟依次執行。
由於每個步驟都可能使用不同的硬體完成,因此聰明的工程師們發明了流水線技術來執行指令,如下圖所示:
CPU實際執行過程中,當執行到指令2時,指令1還沒開始執行,只是剛剛完成了取值操作而已,這樣的好處是加入每個指令都需要執行1ms,那麼指令2的執行不需要等待指令1 執行5ms後才能執行,只需要等待1ms就可以執行了,充分的利用了CPU的效能,但是流水線害怕中斷。
如上圖所示,當後續指令依賴前置指令結果時,流水線便會出現中斷。所以指令的重排序就是為了減少流水線的中斷,提高利用率。
指令重排後:
什麼情況不能指令重排
指令的重排序需要遵從Happen-Before規則:
- 程式順序原則:一個執行緒內保證予以的序列性
- volatile規則: volatile變數的寫,先於讀發生,保證了volatile變數的可見性
- 鎖規則:解鎖必然發生在隨後的加鎖之前
- 傳遞性:A先於B, B先於C,則A先於C
- 執行緒的start()方法先於它的每一個動作
- 執行緒的所有操作先於執行緒的終結(Thead.join())
- 執行緒的中斷(interrupt())先於被中斷執行緒的程式碼
- 物件的建構函式執行、結束先於finalize()方法
參考文獻 : 《Java 高併發程式設計》 葛一鳴 郭超