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

Java內(nèi)存模型之重排序的相關(guān)知識總結(jié)

 更新時間:2021年06月10日 11:21:01   作者:Liziba  
重排序是指編譯器和處理器為了優(yōu)化性能而對指令序列進行重新排序的一種手段,文中詳細介紹了Java重排序的相關(guān)知識,需要的朋友可以參考下

一、數(shù)據(jù)依賴性

如果兩個操作訪問同一個變量,而且這兩個操作中有一個操作為寫操作,此時這兩個操作之間存在數(shù)據(jù)依賴性。數(shù)據(jù)依賴性分為三種,如表所示:

名稱 代碼示例 說明
寫后讀 a=1;b=a; 寫一個變量后,再讀這個位置
寫后寫 a=1;a=2; 寫一個變量后,在寫這個變量
讀后寫 a=b;b=1; 讀一個變量后,再寫這個變量

上面的這三種情況,只要重排序了兩個操作的執(zhí)行順序,程序的執(zhí)行結(jié)果就會被改變。編譯器和處理器針對單個處理器中執(zhí)行的指令序列和單個線程中執(zhí)行的操作重排序時,會遵守數(shù)據(jù)依賴性,編譯器和處理器不會改變存在數(shù)據(jù)依賴關(guān)系的兩個操作的執(zhí)行順序。(不同處理器和不同線程之間的數(shù)據(jù)依賴性不被編譯器和處理器考慮)。

二、as-if-serial語義

as-if-serial語義指的是:不管怎么重排序,單線程執(zhí)行程序的執(zhí)行結(jié)果不能被改變。編譯器、runtime和處理器都必須遵守as-if-serial語義。

為了遵守as-if-serial語義,編譯器和處理器不會對存在數(shù)據(jù)依賴關(guān)系的操作做重排序,因為 這種重排序會改變執(zhí)行結(jié)果。但是,如果操作之間不存在數(shù)據(jù)依賴關(guān)系,這些操作就可能被編譯器和處理器重排序。

舉例說明,計算圓面積的代碼示例:

double pi = 3.14;			//	A
double r = 1.0;				//	B
double area = pi * r;		//	C

上面3個操作的數(shù)據(jù)依賴關(guān)系如下所示:

在這里插入圖片描述

3個操作之間的依賴關(guān)系

解釋:A和B之間存在數(shù)據(jù)依賴關(guān)系,同時B和C之間也存在數(shù)據(jù)依賴關(guān)系。因此在最終執(zhí)行的指令序列中,C不可能被排到A和B的前面(C排到A和B的前面,程序的結(jié)果將會被改變)。但A和B之間沒有數(shù)據(jù)依賴關(guān)系,編譯器和處理器可重排序A和B之間的執(zhí)行順序。

重排序后存在如下的執(zhí)行可能:

在這里插入圖片描述

總結(jié):as-if-serial語義吧單線程程序保護起來了,遵守as-if-serial語義的編譯器、runtime和處理器共同為編寫單線程程序的程序員創(chuàng)建了一個錯誤的幻覺單線程程序是按程序的順序來執(zhí)行的。as-if-serial語義使單線程程序員無需擔心重排序會干擾他們,也無需擔心內(nèi)存可見性問題。

三、程序順序規(guī)則

根據(jù)happens-before的程序規(guī)則,上面計算圓的面積的示例代碼存在3個happens-before關(guān)系。

1.A happens-before B

2.B happens-before C

3.A happens-before C

A happens-before C是根據(jù)1和2推導(dǎo)出來的。

雖然A happens-before B但是實際執(zhí)行時B卻可以排在A前面執(zhí)行(在上面的執(zhí)行圖中)。如果A happens-before B,JMM并不要求A一定要在B之前執(zhí)行,JMM僅僅要求前一個操作(執(zhí)行的結(jié)果)對后一個操作可見,且前一個操作按順序排在第二個操作之前。這里A的執(zhí)行結(jié)果不需要對B可見;而且重排序操作A和操作B后的執(zhí)行結(jié)果,與A和操作B按happens-before順序執(zhí)行的結(jié)果一致。在這種情況下,JMM會認為這種重排序并不非法(not illegal),JMM運行這種重排序。
在計算機中,軟件技術(shù)和硬件技術(shù)有一個共同目標:再不改變程序執(zhí)行結(jié)果的前提下,盡可能提高并行度。編譯器和處理區(qū)遵從這一目標,從happens-before的定義我們可以看出,JMM同樣也遵循這一目標。

四、重排序?qū)Χ嗑€程的影響

重排序是否會影響多線程的執(zhí)行結(jié)果呢?

package com.lizba.p1;

/**
 * <p>
 *
 * </p>
 *
 * @Author: Liziba
 * @Date: 2021/6/7 23:01
 */
public class ReorderExample {

    // 定義變量a
    int a = 0;
    // flag變量是個標記,用來標志變量a是否被寫入
    boolean flag = false;

    public void writer() {
        a = 1;                           // 1
        flag = true;                     // 2
    }

    public void reader() {
        if (flag) {                      // 3
            int i = a * a;               // 4
            System.out.println("i:" + i);
        }
    }


    /**
     * 測試
     * 
     * @param args
     */
    public static void main(String[] args) {

        final ReorderExample re = new ReorderExample();

        new Thread() {
            public void run() {
                re.writer();
            }
        }.start();

        new Thread() {
            public void run() {
                re.reader();
            }
        }.start();
    }

}

這里假設(shè)兩個線程A和B,A首先執(zhí)行write(),B再執(zhí)行readr()。線程B在執(zhí)行操作4時,能否看到線程A在操作1對共享變量a的寫入呢?

答案是:不一定能!
由于操作1和操作2沒有數(shù)據(jù)依賴關(guān)系,編譯器和處理器可以對這兩個操作重排序;同樣,操作3和操作4沒有數(shù)據(jù)依賴關(guān)系,編譯器和處理器也可以多這兩個操作重排序。

假設(shè)操作1和操作2重排序:(虛箭線代表錯誤的讀操作)

在這里插入圖片描述

程序執(zhí)行時序圖

如上圖操作1和操作2發(fā)生了重排序。程序執(zhí)行時,線程A首先寫標記變量flag,隨后線程B讀取這個變量,條件判斷為真,線程B讀取變量a的值。此時,變量a還沒有被線程A寫入,在這里多線程程序的語義被重排序破壞了。

設(shè)操作3和操作4重排序:

在這里插入圖片描述

程序執(zhí)行時序圖

在上述執(zhí)行方式的程序中,操作3和操作4存在控制依賴關(guān)系。當代碼中存在控制依賴性時,會影響指令并行度。為此編譯器和處理器會采用猜測(Speculation)執(zhí)行來克服控制相關(guān)性對并行度的影響。以處理器的猜測執(zhí)行為例,執(zhí)行現(xiàn)場B的處理器可提前讀取并行計算a*a,然后計算結(jié)果保存到一個名為重排序緩沖(Recorder Buffer, ROB)的硬件緩存中。當操作3的條件判斷為真時,就把計算結(jié)果寫入變量i中。
在上圖中可以看出,猜測執(zhí)行實質(zhì)上對操作3和4做了重排序。重排序在這里破壞了多線程程序的語義!
在單線程程序中,對存在控制依賴性的操作重排序,不會改變執(zhí)行結(jié)果(這也是as-if-serial語義允許對存在控制依賴的操作做重排序的原因);但是在多線程中,對存在控制依賴的操作重排序,可能會改變程序的執(zhí)行結(jié)果。

到此這篇關(guān)于Java內(nèi)存模型之重排序的相關(guān)知識總結(jié)的文章就介紹到這了,更多相關(guān)Java重排序內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • shiro多驗證登錄代碼實例及問題解決

    shiro多驗證登錄代碼實例及問題解決

    這篇文章主要介紹了shiro多驗證登錄代碼實例及問題解決,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友可以參考下
    2019-12-12
  • Java實現(xiàn)字符串解析為日期時間的方法示例

    Java實現(xiàn)字符串解析為日期時間的方法示例

    這篇文章主要介紹了Java實現(xiàn)字符串解析為日期時間的方法,結(jié)合具體實例形式分析了java日期時間字符串的解析操作相關(guān)實現(xiàn)技巧,需要的朋友可以參考下
    2017-04-04
  • Java如何通過ssh遠程連接主機并執(zhí)行命令

    Java如何通過ssh遠程連接主機并執(zhí)行命令

    這篇文章主要介紹了Java如何通過ssh遠程連接主機并執(zhí)行命令問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • Java ArrayList 數(shù)組之間相互轉(zhuǎn)換

    Java ArrayList 數(shù)組之間相互轉(zhuǎn)換

    本文通過代碼示例給大家講解arraylist轉(zhuǎn)化為數(shù)組,然后數(shù)組轉(zhuǎn)化為arraylist的相關(guān)資料,感興趣的朋友一起看看吧
    2015-11-11
  • Java Linkedlist原理及實例詳解

    Java Linkedlist原理及實例詳解

    這篇文章主要介紹了Java Linkedlist原理及實例詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友可以參考下
    2020-01-01
  • Java實現(xiàn)List集合轉(zhuǎn)樹形結(jié)構(gòu)的示例詳解

    Java實現(xiàn)List集合轉(zhuǎn)樹形結(jié)構(gòu)的示例詳解

    在開發(fā)中,我們通常需要將從數(shù)據(jù)庫中查詢的集合數(shù)據(jù)轉(zhuǎn)換成類似文件系統(tǒng)一樣的樹形集合。本文將利用Java語言實現(xiàn)這一功能,感興趣的可以了解一下
    2022-08-08
  • Java中字符串替換的4種方法代碼舉例

    Java中字符串替換的4種方法代碼舉例

    這篇文章主要介紹了Java中四種字符串替換方法,分別是String.replace()、String.replaceAll()、String.replaceFirst()和StringBuilder.replace(),并對比了它們的特點和適用場景,需要的朋友可以參考下
    2025-02-02
  • 淺談Java線程間通信之wait/notify

    淺談Java線程間通信之wait/notify

    下面小編就為大家?guī)硪黄獪\談Java線程間通信之wait/notify。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • java8 Stream流逐行處理文本文件

    java8 Stream流逐行處理文本文件

    這篇文章主要介紹了java8 Stream流逐行處理文本文件的相關(guān)資料,文中講解非常細致,代碼幫助大家更好的理解和學(xué)習,感興趣的朋友可以了解下
    2020-07-07
  • Spring使用注解實現(xiàn)Bean的自動裝配

    Spring使用注解實現(xiàn)Bean的自動裝配

    大家好,本篇文章主要講的是Spring使用注解實現(xiàn)Bean的自動裝配,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下
    2022-02-02

最新評論

巴东县| 新龙县| 黑龙江省| 铜陵市| 延安市| 攀枝花市| 郴州市| 老河口市| 望奎县| 浦北县| 庆云县| 晋江市| 呈贡县| 望奎县| 彰化县| 祁阳县| 九龙坡区| 和硕县| 罗城| 荔波县| 南京市| 南漳县| 桃园县| 酉阳| 沾益县| 石林| 黎川县| 乐都县| 汽车| 丰都县| 林甸县| 酉阳| 江川县| 永德县| 海安县| 松阳县| 漳浦县| 新巴尔虎左旗| 皮山县| 台山市| 武汉市|