您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關Java中怎么利用volatile防止指令重排,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
計算機在執行程序時,為了提高性能,編譯器和處理器一般會進行指令重排,一般分為以下三種:
指令重排有以下三個特點:
1.單線程環境下指令重排后可以保證與順序執行指令的結果一致(就是不進行指令重排的情況)
//原來的執行順序 a=1; b=0; //進行指令重排后執行 b=0; a=1;
這兩個順序執行的指令結果都是a=1,b=0
2.進行指令重排的時候要考慮指令之間的數據依賴性(某個指令的數據需要根據另一個指令的數據獲得)
//原來的執行順序 a=0; //指令1 a=10; //指令2 b=a+1; //指令3 //進行指令重排后 a=0; b=a+1; a=10;
此時兩種順序輸出的結果就不一樣了,這是因為指令3的數據依賴于指令2,單線程環境下指令重排不會出現這種情況。
3.多線程環境下,多個線程交替執行,由于編譯器會進行指令重排,結果無法預測。
串行的代碼確實會按代碼語意正確的執行(就是編寫的代碼的運行邏輯),但是編譯器對于代碼本身的優化卻并不一定會按實際的代碼一步一步的執行,就比如下面這段代碼
public void process() { int a = 10; #指令1 int b = 20; #指令2 }
代碼的執行過程一定是是int a=10然后int b=20,但是代碼轉換成計算機可以識別的指令可能是指令2,指令1。
我們知道指令的執行可以分為這幾步:
取址 IF
譯碼和取寄存器操作數 ID
執行或者有效地址計算 EX (ALU邏輯計算單元)
存儲器訪問 MEM
寫回 WB (寄存器)
一段代碼并不是由單條指令就可以執行完畢的,而是通過流水線技術來執行多條指令。
流水線技術是一種將指令分解為多步,并讓不同指令的各步操作重疊,從而實現幾條指令并行處理,這樣就提高了指令的執行速度
簡單來說就是通過指令重排,可以使用流水線技術實現指令的細分,然后實現幾條指令的并行處理,從而提高速度
這就涉及到一個概念內存屏障(內存柵欄),它是一個cpu指令,有兩個作用:
保證某些特定操作的執行順序
保證某些變量的內存可見性(實現了volatile保證可見性)
編譯器和處理器都可以進行指令重排,那么如果我們在程序中插入一條Memery Barrier(內存屏障),那么就會告訴編譯器和cpu不能對這條指令進行重排,也就是說通過插入內存屏障,使屏障前后的指令不會進行重排優化,內存屏障還可以強制刷出cpu的緩存,因此cpu上的線程都能讀到這些數據的最新版本。
簡單來說就是插入內存屏障后告訴cpu和編譯器,這個內存屏障前后的指令你不要給我進行重排序
內存屏障分為四種:
StoreStore屏障、StoreLoad屏障、LoadLoad屏障、LoadStore屏障。
Load相當于讀屏障
Store相當于寫屏障
關于Java中怎么利用volatile防止指令重排就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。