Java中volatile防止指令重排
volatile可以防止指令重排,在多線程環(huán)境下有時候我們需要使用volatile來防止指令重排,來保證代碼運行后數(shù)據(jù)的準確性
什么是指令重排?計算機在執(zhí)行程序時,為了提高性能,編譯器和處理器一般會進行指令重排,一般分為以下三種:
指令重排有以下三個特點:
1.單線程環(huán)境下指令重排后可以保證與順序執(zhí)行指令的結(jié)果一致(就是不進行指令重排的情況)
//原來的執(zhí)行順序a=1;b=0;//進行指令重排后執(zhí)行b=0;a=1;
這兩個順序執(zhí)行的指令結(jié)果都是a=1,b=0
2.進行指令重排的時候要考慮指令之間的數(shù)據(jù)依賴性(某個指令的數(shù)據(jù)需要根據(jù)另一個指令的數(shù)據(jù)獲得)
//原來的執(zhí)行順序a=0; //指令1a=10; //指令2b=a+1; //指令3//進行指令重排后a=0;b=a+1; a=10;
此時兩種順序輸出的結(jié)果就不一樣了,這是因為指令3的數(shù)據(jù)依賴于指令2,單線程環(huán)境下指令重排不會出現(xiàn)這種情況。
3.多線程環(huán)境下,多個線程交替執(zhí)行,由于編譯器會進行指令重排,結(jié)果無法預測。
為什么指令重排能夠提高性能串行的代碼確實會按代碼語意正確的執(zhí)行(就是編寫的代碼的運行邏輯),但是編譯器對于代碼本身的優(yōu)化卻并不一定會按實際的代碼一步一步的執(zhí)行,就比如下面這段代碼
public void process() { int a = 10; #指令1 int b = 20; #指令2}
代碼的執(zhí)行過程一定是是int a=10然后int b=20,但是代碼轉(zhuǎn)換成計算機可以識別的指令可能是指令2,指令1。
我們知道指令的執(zhí)行可以分為這幾步:
取址 IF 譯碼和取寄存器操作數(shù) ID 執(zhí)行或者有效地址計算 EX (ALU邏輯計算單元) 存儲器訪問 MEM 寫回 WB (寄存器)一段代碼并不是由單條指令就可以執(zhí)行完畢的,而是通過流水線技術(shù)來執(zhí)行多條指令。
流水線技術(shù)是一種將指令分解為多步,并讓不同指令的各步操作重疊,從而實現(xiàn)幾條指令并行處理,這樣就提高了指令的執(zhí)行速度
簡單來說就是通過指令重排,可以使用流水線技術(shù)實現(xiàn)指令的細分,然后實現(xiàn)幾條指令的并行處理,從而提高速度
volatile是怎么禁止指令重排的?這就涉及到一個概念內(nèi)存屏障(內(nèi)存柵欄),它是一個cpu指令,有兩個作用:
保證某些特定操作的執(zhí)行順序 保證某些變量的內(nèi)存可見性(實現(xiàn)了volatile保證可見性)編譯器和處理器都可以進行指令重排,那么如果我們在程序中插入一條Memery Barrier(內(nèi)存屏障),那么就會告訴編譯器和cpu不能對這條指令進行重排,也就是說通過插入內(nèi)存屏障,使屏障前后的指令不會進行重排優(yōu)化,內(nèi)存屏障還可以強制刷出cpu的緩存,因此cpu上的線程都能讀到這些數(shù)據(jù)的最新版本。
簡單來說就是插入內(nèi)存屏障后告訴cpu和編譯器,這個內(nèi)存屏障前后的指令你不要給我進行重排序
內(nèi)存屏障分為四種:
StoreStore屏障、StoreLoad屏障、LoadLoad屏障、LoadStore屏障。
Load相當于讀屏障 Store相當于寫屏障到此這篇關(guān)于Java中volatile防止指令重排 的文章就介紹到這了,更多相關(guān)Java volatile防止指令重排 內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!
相關(guān)文章:
1. XML入門的常見問題(三)2. HTTP協(xié)議常用的請求頭和響應頭響應詳解說明(學習)3. ASP基礎(chǔ)入門第四篇(腳本變量、函數(shù)、過程和條件語句)4. HTML5實戰(zhàn)與剖析之觸摸事件(touchstart、touchmove和touchend)5. .NET Framework各版本(.NET2.0 3.0 3.5 4.0)區(qū)別6. ASP將數(shù)字轉(zhuǎn)中文數(shù)字(大寫金額)的函數(shù)7. XML在語音合成中的應用8. jscript與vbscript 操作XML元素屬性的代碼9. php使用正則驗證密碼字段的復雜強度原理詳細講解 原創(chuàng)10. 不要在HTML中濫用div
