日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

如何 方法内指令重排 进制_谈谈指令重排

發布時間:2025/3/12 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何 方法内指令重排 进制_谈谈指令重排 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這個知識點也是很多人說不清道不明的地方,感覺都知道,說又說不出來。為什么會這樣呢?因為這幾個字,很容易被當成動詞去理解,其實正確的理解是當成名詞,即指令重排現象。那什么時候會產生指令重排現象呢?兩個階段:1、編譯期;2、運行期。

編譯期指令重排

解釋型語言是在運行期間執行編譯+運行動作,所以運行效率較編譯型語言低。Java既可以作為解釋型語言去用,也可以作為編譯型語言。但是主流的做法是當成編譯型語言在用。那Java在編譯期做了指令重排優化嗎?做了哪些優化?能不能讓我看看?為了滿足大家的好奇,安排。

這里先解釋下編譯期:像c/c++只有一個編譯期,就是調用gcc命令將c/c++代碼編譯成匯編代碼。但是Java中有兩個編譯期:1、調用javac命令將Java代碼編譯成Java字節碼;2、Unix派系平臺上調用gcc命令將openjdk源碼編譯成匯編代碼。網上所有的文章都是在講第一種,而且都是講概念,以訛傳訛。我這篇文章不僅兩種都講,還都用代碼+圖片的方式證明給你看。所以想學底層,不找一個靠譜的師傅是學不會學不明白的,因為第一你不知道這個知識點牽扯得有多深,第二兩個觀點擺在你面前,你不知道哪個對那個錯。

這里我先把結論給大家吧:編譯期間,Java中所謂的指令重排主要是說編譯openjdk時的指令重排,將Java代碼編譯成Java字節碼是沒有做指令重排的。即你加不加volatile,生成的字節碼文件是一樣的。是不是顛覆了你對這塊的認知呢!不信?看案例。

可能有人要問了,如果加不加volatile生成的字節碼文件都一個樣,那在運行的時候JVM是怎么知道的呢?類屬性在JVM中存儲的時候會有一個屬性:Access flags。JVM在運行的時候就是通過該屬性來判斷操作的類屬性有沒有加volatile修飾,上圖。

1、上神秘代碼

public class Test3 {

public static /* volatile */ int found = 0;

public static void main(String[] args) {

new Thread(new Runnable() {

public void run() {

System.out.println("等基友送筆來...");

while (0 == found) {

}

System.out.println("筆來了,開始寫字...");

}

}, "我線程").start();

new Thread(new Runnable() {

public void run() {

try {

Thread.sleep(2000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("基友找到筆了,送過去...");

change();

}

}, "基友線程").start();

}

public static void change() {

found = 1;

}

}

稍微解釋下這段代碼:有兩個線程:我線程、基友線程。『我線程』通過死循環阻塞在那里等待『基友線程』找到筆送過來,然后開始寫字。『基友線程』等待一會就去找筆,找到了就送過去。

2、編譯成Java字節碼(沒加volatile)

3、編譯成Java字節碼(加了volatile)

可以發現加不加volatile,生成的字節碼是一樣的。

4、編譯器優化

指令重排是編譯器優化中的一種,編譯openjdk是啟用了O2級編譯器優化,如圖。

O2級優化做了哪些優化?比如優化無效代碼、編譯期完成簡單運算、處理編譯期屏障……那gcc有多少級優化?有興趣的童鞋可以自行學習,百度搜索關鍵詞:-O2。

優化無效代碼,看圖(我就不貼C++代碼了)

運行期指令重排

不知道大家有沒有聽過一個詞:CPU亂序執行。亂序執行是相對于順序執行來說的。計算機剛被發明的時候都是順序執行,后來為了提升CPU運行效率,升級成了亂序執行。那為什么亂序執行就提高了運行效率呢?有興趣的童鞋可以去研究下,關鍵詞:指令流水線。所以計算機這行,如果你覺得大學學的那些基礎知識不重要,你看我的文章就明白有多重要。這行走到最后較量的就是這些東西,就是看誰研究得更深入更底層更明了。

因為現在的CPU都是采用亂序執行,這樣在運行程序的過程中就帶來了指令重排的現象。這是在運行期,在CPU內部發生的,我就沒辦法證明給你看了。但就算是亂序執行提高了效率,那也不能改變我程序的意愿,這就引出了一個概念:as-if-serial。

何謂as-if-serial呢?簡單的說就是不管你在編譯期或者在運行期怎么做指令重排,單線程環境下程序的執行結果不能改變。說白了這是指令重排的底線,是必須遵守的規范。那如何保證呢?這就引出了另外兩個難以理解的知識點:happens-before、內存屏障。

happens-before是做什么的呢?簡單的說就是告訴寫JVM的人,你寫JVM的時候要遵循這幾條規則,這幾條規則是你JVM默認要做到的,而不用程序猿在寫代碼的時候需要去想去做控制。比如對象的初始化動作一定要先于finalize方法執行前完成。其他幾個規則我就不細說了,都很好理解,童鞋們自行去學習下。

有些流程的順序是可以提前知曉并確定下來,但有些流程的順序是無法提前知曉的,比如你公司的業務,寫JVM的人肯定不知道,所以依然需要程序猿根據業務需要來控制,那從JVM層面來說,我給你提供機制。內存屏障就是這種機制中的一種,其他的還有各種鎖。關于內存屏障,我之前已經寫了一篇文章深入講解了這塊,有興趣的同學可以去看看。子牙老師:聊聊內存屏障?zhuanlan.zhihu.com

至此,指令重排就算講明白了,不曉得童鞋們有么有看明白、理解到位。

子牙老師喜歡分析硬核文章,都會在個人公眾號(啟明南)首發。想第一時間獲得通知嗎?那就關注一波吧。

總結

以上是生活随笔為你收集整理的如何 方法内指令重排 进制_谈谈指令重排的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。