最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

關(guān)于指令重排現(xiàn)象的兩個(gè)階段詳解

 更新時(shí)間:2022年01月30日 13:20:02   作者:子牙_公號(hào)硬核子牙  
這個(gè)知識(shí)點(diǎn)也是很多人說(shuō)不清道不明的地方,感覺都知道,說(shuō)又說(shuō)不出來(lái)。為什么會(huì)這樣呢?因?yàn)檫@幾個(gè)字,很容易被當(dāng)成動(dòng)詞去理解,其實(shí)正確的理解是當(dāng)成名詞,即指令重排現(xiàn)象

那什么時(shí)候會(huì)產(chǎn)生指令重排現(xiàn)象呢??jī)蓚€(gè)階段:1、編譯期;2、運(yùn)行期。

編譯期指令重排

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

這里先解釋下編譯期:像c/c++只有一個(gè)編譯期,就是調(diào)用gcc命令將c/c++代碼編譯成匯編代碼。

但是Java中有兩個(gè)編譯期:

  • 1、調(diào)用javac命令將Java代碼編譯成Java字節(jié)碼;
  • 2、Unix派系平臺(tái)上調(diào)用gcc命令將openjdk源碼編譯成匯編代碼。

網(wǎng)上所有的文章都是在講第一種,而且都是講概念,以訛傳訛。我這篇文章不僅兩種都講,還都用代碼+圖片的方式證明給你看。所以想學(xué)底層,不找一個(gè)靠譜的師傅是學(xué)不會(huì)學(xué)不明白的,因?yàn)榈谝荒悴恢肋@個(gè)知識(shí)點(diǎn)牽扯得有多深,第二兩個(gè)觀點(diǎn)擺在你面前,你不知道哪個(gè)對(duì)那個(gè)錯(cuò)。

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

可能有人要問了,如果加不加volatile生成的字節(jié)碼文件都一個(gè)樣,那在運(yùn)行的時(shí)候JVM是怎么知道的呢?類屬性在JVM中存儲(chǔ)的時(shí)候會(huì)有一個(gè)屬性:Access flags。JVM在運(yùn)行的時(shí)候就是通過該屬性來(lái)判斷操作的類屬性有沒有加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("等基友送筆來(lái)...");
          while (0 == found) {
          }
          System.out.println("筆來(lái)了,開始寫字...");
       }
    }, "我線程").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;
 }
}

稍微解釋下這段代碼:有兩個(gè)線程:我線程、基友線程?!何揖€程』通過死循環(huán)阻塞在那里等待『基友線程』找到筆送過來(lái),然后開始寫字?!夯丫€程』等待一會(huì)就去找筆,找到了就送過去。

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

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

可以發(fā)現(xiàn)加不加volatile,生成的字節(jié)碼是一樣的。

4、編譯器優(yōu)化

指令重排是編譯器優(yōu)化中的一種,編譯openjdk是啟用了O2級(jí)編譯器優(yōu)化,如圖。

O2級(jí)優(yōu)化做了哪些優(yōu)化?比如優(yōu)化無(wú)效代碼、編譯期完成簡(jiǎn)單運(yùn)算、處理編譯期屏障……那gcc有多少級(jí)優(yōu)化?有興趣的童鞋可以自行學(xué)習(xí),百度搜索關(guān)鍵詞:-O2。

優(yōu)化無(wú)效代碼,看圖(我就不貼C++代碼了)

運(yùn)行期指令重排

不知道大家有沒有聽過一個(gè)詞:CPU亂序執(zhí)行。亂序執(zhí)行是相對(duì)于順序執(zhí)行來(lái)說(shuō)的。計(jì)算機(jī)剛被發(fā)明的時(shí)候都是順序執(zhí)行,后來(lái)為了提升CPU運(yùn)行效率,升級(jí)成了亂序執(zhí)行。

那為什么亂序執(zhí)行就提高了運(yùn)行效率呢?有興趣的童鞋可以去研究下,關(guān)鍵詞:指令流水線。

所以計(jì)算機(jī)這行,如果你覺得大學(xué)學(xué)的那些基礎(chǔ)知識(shí)不重要,你看我的文章就明白有多重要。這行走到最后較量的就是這些東西,就是看誰(shuí)研究得更深入更底層更明了。

因?yàn)楝F(xiàn)在的CPU都是采用亂序執(zhí)行,這樣在運(yùn)行程序的過程中就帶來(lái)了指令重排的現(xiàn)象。這是在運(yùn)行期,在CPU內(nèi)部發(fā)生的,我就沒辦法證明給你看了。但就算是亂序執(zhí)行提高了效率,那也不能改變我程序的意愿,這就引出了一個(gè)概念:as-if-serial。

何謂as-if-serial呢?簡(jiǎn)單的說(shuō)就是不管你在編譯期或者在運(yùn)行期怎么做指令重排,單線程環(huán)境下程序的執(zhí)行結(jié)果不能改變。說(shuō)白了這是指令重排的底線,是必須遵守的規(guī)范。那如何保證呢?這就引出了另外兩個(gè)難以理解的知識(shí)點(diǎn):happens-before、內(nèi)存屏障。

happens-before是做什么的呢?簡(jiǎn)單的說(shuō)就是告訴寫JVM的人,你寫JVM的時(shí)候要遵循這幾條規(guī)則,這幾條規(guī)則是你JVM默認(rèn)要做到的,而不用程序猿在寫代碼的時(shí)候需要去想去做控制。比如對(duì)象的初始化動(dòng)作一定要先于finalize方法執(zhí)行前完成。其他幾個(gè)規(guī)則我就不細(xì)說(shuō)了,都很好理解,童鞋們自行去學(xué)習(xí)下。

有些流程的順序是可以提前知曉并確定下來(lái),但有些流程的順序是無(wú)法提前知曉的,比如你公司的業(yè)務(wù),寫JVM的人肯定不知道,所以依然需要程序猿根據(jù)業(yè)務(wù)需要來(lái)控制,那從JVM層面來(lái)說(shuō),我給你提供機(jī)制。內(nèi)存屏障就是這種機(jī)制中的一種,其他的還有各種鎖。關(guān)于內(nèi)存屏障,我之前已經(jīng)寫了一篇文章深入講解了這塊,有興趣的同學(xué)可以去看看,傳送門 內(nèi)存屏障由來(lái)及實(shí)現(xiàn)思路

以上就是關(guān)于指令重排現(xiàn)象的兩個(gè)階段詳解的詳細(xì)內(nèi)容,更多關(guān)于指令重排現(xiàn)象的兩個(gè)階段的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Git 教程之遠(yuǎn)程倉(cāng)庫(kù)詳解

    Git 教程之遠(yuǎn)程倉(cāng)庫(kù)詳解

    本文主要介紹Git 遠(yuǎn)程倉(cāng)庫(kù)的知識(shí),這里整理了相關(guān)資料,及命令詳解,圖文并茂的介紹該部分內(nèi)容,有需要的小伙伴可以參考下
    2016-09-09
  • Git操作規(guī)范之tag的使用技巧詳解

    Git操作規(guī)范之tag的使用技巧詳解

    這篇文章主要為大家介紹了Git操作規(guī)范之tag的使用技巧詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • IntelliJ IDEA2020.3 新特性(小結(jié))

    IntelliJ IDEA2020.3 新特性(小結(jié))

    這篇文章主要介紹了IntelliJ IDEA 2020.3 新特性,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧
    2020-12-12
  • 詳解Hadoop2.7.2 編譯64位源碼

    詳解Hadoop2.7.2 編譯64位源碼

    這篇文章主要介紹了Hadoop2.7.2 編譯64位源碼的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-02-02
  • 詳解VScode 配置為 LaTeX 編輯器(IDE)

    詳解VScode 配置為 LaTeX 編輯器(IDE)

    這篇文章主要介紹了詳解VScode 配置為 LaTeX 編輯器,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • 網(wǎng)站性能優(yōu)化之HTTP請(qǐng)求過程簡(jiǎn)述

    網(wǎng)站性能優(yōu)化之HTTP請(qǐng)求過程簡(jiǎn)述

    網(wǎng)站性能優(yōu)化中首要的一條就是要減少HTTP請(qǐng)求,那么為要減少HTTP請(qǐng)求呢?其實(shí)有些HTTP分析工具可以幫我們了解當(dāng)瀏覽器請(qǐng)求一個(gè)資源時(shí)大致需要經(jīng)歷的哪些過程
    2011-12-12
  • ChatGPT如何寫好Prompt編程示例詳解

    ChatGPT如何寫好Prompt編程示例詳解

    這篇文章主要為大家介紹了ChatGPT如何寫好Prompt編程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • 完美解決瀏覽器輸入http被自動(dòng)跳轉(zhuǎn)至https問題

    完美解決瀏覽器輸入http被自動(dòng)跳轉(zhuǎn)至https問題

    很多朋友問小編瀏覽器輸入http被自動(dòng)跳轉(zhuǎn)至https問題,到底該怎么解決呢,其實(shí)解決方法很簡(jiǎn)單,主要關(guān)閉瀏覽器的HSTS功能就可以了,關(guān)于http自動(dòng)跳轉(zhuǎn)至https的解決方法跟隨小編一起看看吧
    2021-05-05
  • Git提交到錯(cuò)誤分支如何解決

    Git提交到錯(cuò)誤分支如何解決

    如果不慎將代碼提交至錯(cuò)誤分支,可以通過以下步驟糾正:1.確認(rèn)當(dāng)前分支及提交記錄,2.切換至正確分支,若不存在則創(chuàng)建,3.使用cherry-pick或rebase方法將提交從錯(cuò)誤分支轉(zhuǎn)移到正確分支,4.清理錯(cuò)誤分支記錄,可以選擇重置或刪除錯(cuò)誤提交
    2024-09-09
  • HTML轉(zhuǎn)義字符&npsp;表示non-breaking space \xa0

    HTML轉(zhuǎn)義字符&npsp;表示non-breaking space \xa0

    HTML轉(zhuǎn)義字符&npsp;表示non-breaking space,unicode編碼為u'\xa0',超出gbk編碼范圍,這里就為大家分享一下
    2020-02-02

最新評(píng)論

黄山市| 大化| 博爱县| 昌都县| 新源县| 宁安市| 麻栗坡县| 汽车| 定兴县| 北辰区| 略阳县| 阳山县| 衡山县| 庆元县| 大同县| 峨眉山市| 泰来县| 女性| 白玉县| 垫江县| 宣恩县| 商河县| 海晏县| 江安县| 肇东市| 通海县| 鄢陵县| 温宿县| 通化市| 榕江县| 玉田县| 平原县| 勐海县| 都安| 常山县| 静宁县| 巴南区| 富锦市| 遂川县| 米林县| 五寨县|