欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

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

如果兩個(gè)操作訪(fǎng)問(wèn)同一個(gè)變量,而且這兩個(gè)操作中有一個(gè)操作為寫(xiě)操作,此時(shí)這兩個(gè)操作之間存在數(shù)據(jù)依賴(lài)性。數(shù)據(jù)依賴(lài)性分為三種,如表所示:

名稱(chēng) 代碼示例 說(shuō)明
寫(xiě)后讀 a=1;b=a; 寫(xiě)一個(gè)變量后,再讀這個(gè)位置
寫(xiě)后寫(xiě) a=1;a=2; 寫(xiě)一個(gè)變量后,在寫(xiě)這個(gè)變量
讀后寫(xiě) a=b;b=1; 讀一個(gè)變量后,再寫(xiě)這個(gè)變量

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

二、as-if-serial語(yǔ)義

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

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

舉例說(shuō)明,計(jì)算圓面積的代碼示例:

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

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

在這里插入圖片描述

3個(gè)操作之間的依賴(lài)關(guān)系

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

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

在這里插入圖片描述

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

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

根據(jù)happens-before的程序規(guī)則,上面計(jì)算圓的面積的示例代碼存在3個(gè)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)出來(lái)的。

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

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

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

package com.lizba.p1;

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

    // 定義變量a
    int a = 0;
    // flag變量是個(gè)標(biāo)記,用來(lái)標(biāo)志變量a是否被寫(xiě)入
    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);
        }
    }


    /**
     * 測(cè)試
     * 
     * @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è)兩個(gè)線(xiàn)程A和B,A首先執(zhí)行write(),B再執(zhí)行readr()。線(xiàn)程B在執(zhí)行操作4時(shí),能否看到線(xiàn)程A在操作1對(duì)共享變量a的寫(xiě)入呢?

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

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

在這里插入圖片描述

程序執(zhí)行時(shí)序圖

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

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

在這里插入圖片描述

程序執(zhí)行時(shí)序圖

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

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

相關(guān)文章

  • Java將一個(gè)正整數(shù)分解質(zhì)因數(shù)的代碼

    Java將一個(gè)正整數(shù)分解質(zhì)因數(shù)的代碼

    這篇文章主要介紹了將一個(gè)正整數(shù)分解質(zhì)因數(shù)。例如:輸入90,打印出90=2*3*3*5,需要的朋友可以參考下
    2017-02-02
  • Java中SPI機(jī)制的實(shí)現(xiàn)詳解

    Java中SPI機(jī)制的實(shí)現(xiàn)詳解

    SPI(Service?Provider?Interface),是?JDK?內(nèi)置的一種服務(wù)提供發(fā)現(xiàn)機(jī)制,可以用來(lái)啟用框架擴(kuò)展和替換組件,下面我們就來(lái)看看Java中SPI機(jī)制的具體實(shí)現(xiàn)
    2024-01-01
  • SpringBoot使用ip2region獲取地理位置信息的方法

    SpringBoot使用ip2region獲取地理位置信息的方法

    這篇文章主要介紹了SpringBoot使用ip2region獲取地理位置信息的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • Spring @Value 設(shè)置默認(rèn)值的實(shí)現(xiàn)

    Spring @Value 設(shè)置默認(rèn)值的實(shí)現(xiàn)

    這篇文章主要介紹了Spring @Value 設(shè)置默認(rèn)值的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • SpringBoot整合H2數(shù)據(jù)庫(kù)的操作方法

    SpringBoot整合H2數(shù)據(jù)庫(kù)的操作方法

    H2是一個(gè)Java語(yǔ)言編寫(xiě)的嵌入式數(shù)據(jù)庫(kù),它不受平臺(tái)的限制,同時(shí)H2提供了一個(gè)十分方便的web控制臺(tái),用于操作和管理數(shù)據(jù)庫(kù)內(nèi)容,本文介紹SpringBoot整合H2數(shù)據(jù)庫(kù)的方法,感興趣的朋友一起看看吧
    2024-01-01
  • Java線(xiàn)性結(jié)構(gòu)中的雙向鏈表實(shí)現(xiàn)原理

    Java線(xiàn)性結(jié)構(gòu)中的雙向鏈表實(shí)現(xiàn)原理

    這篇文章將給大家詳細(xì)講解雙向鏈表的內(nèi)容,尤其是會(huì)通過(guò)代碼來(lái)進(jìn)行鏈表的操作,文中的代碼示例介紹的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下
    2023-07-07
  • 教你用java完美封裝微信模板消息的發(fā)送動(dòng)態(tài)

    教你用java完美封裝微信模板消息的發(fā)送動(dòng)態(tài)

    這篇文章主要介紹了教你用java完美封裝微信模板消息的發(fā)送動(dòng)態(tài),文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有很好的幫助,需要的朋友可以參考下
    2021-04-04
  • windows下vscode+vs2019開(kāi)發(fā)JNI的示例

    windows下vscode+vs2019開(kāi)發(fā)JNI的示例

    本文給大家普及windows下vscode+vs2019開(kāi)發(fā)JNI的示例以及各個(gè)環(huán)節(jié)的注意事項(xiàng),文章通過(guò)示例代碼圖文相結(jié)合給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2021-06-06
  • Java實(shí)現(xiàn)的Excel列號(hào)數(shù)字與字母互相轉(zhuǎn)換功能

    Java實(shí)現(xiàn)的Excel列號(hào)數(shù)字與字母互相轉(zhuǎn)換功能

    這篇文章主要介紹了Java實(shí)現(xiàn)的Excel列號(hào)數(shù)字與字母互相轉(zhuǎn)換功能,涉及java針對(duì)Excel相關(guān)數(shù)值與字符串操作技巧,需要的朋友可以參考下
    2018-03-03
  • Java分布式ID中Snowflake雪花算法應(yīng)用實(shí)現(xiàn)

    Java分布式ID中Snowflake雪花算法應(yīng)用實(shí)現(xiàn)

    Snowflake算法作為一種高效且易于實(shí)現(xiàn)的分布式ID生成方案,能夠很好地滿(mǎn)足分布式系統(tǒng)中對(duì)全局唯一ID的需求,本文就來(lái)介紹一下Java分布式ID中Snowflake雪花算法應(yīng)用實(shí)現(xiàn),感興趣的可以了解一下
    2024-07-07

最新評(píng)論