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

Java指令重排序在多線(xiàn)程環(huán)境下的處理方法

 更新時(shí)間:2022年04月24日 08:36:04   作者:Java知識(shí)圖譜  
指令重排在單線(xiàn)程環(huán)境下有利于提高程序的執(zhí)行效率,不會(huì)對(duì)程序產(chǎn)生負(fù)面影響,本文對(duì)多線(xiàn)程指令重排問(wèn)題進(jìn)行復(fù)原,并針對(duì)指令重排給出相應(yīng)的解決方案,需要的朋友參考下吧

一、序言

指令重排在單線(xiàn)程環(huán)境下有利于提高程序的執(zhí)行效率,不會(huì)對(duì)程序產(chǎn)生負(fù)面影響;在多線(xiàn)程環(huán)境下,指令重排會(huì)給程序帶來(lái)意想不到的錯(cuò)誤。

本文對(duì)多線(xiàn)程指令重排問(wèn)題進(jìn)行復(fù)原,并針對(duì)指令重排給出相應(yīng)的解決方案。

二、問(wèn)題復(fù)原

(一)關(guān)聯(lián)變量

下面給出一個(gè)能夠百分之百?gòu)?fù)原指令重排的例子。

ublic class D {
    static Integer a;
    static Boolean flag;
    
    public static void writer() {
        a = 1;
        flag = true;
    }
    public static void reader() {
        if (flag != null && flag) {
            System.out.println(a);
            a = 0;
            flag = false;
        }
}

1、結(jié)果預(yù)測(cè)

reader方法僅在flag變量為true時(shí)向控制臺(tái)打印變量a的值。

writer方法先執(zhí)行變量a的賦值操作,后執(zhí)行變量flag的賦值操作。

如果按照上述分析邏輯,那么控制臺(tái)打印的結(jié)果一定全為1。

2、指令重排

假如代碼未發(fā)生指令重排,那么當(dāng)flag變量為true時(shí),變量a一定為1。

上述代碼中關(guān)于變量a和變量flag在兩個(gè)方法類(lèi)均存在指令重排的情況。

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

通過(guò)觀察日志輸出,發(fā)現(xiàn)有大量的0輸出。

當(dāng)writer方法內(nèi)部發(fā)生指令重排時(shí),flag變量先完成賦值,此時(shí)假如當(dāng)前線(xiàn)程發(fā)生中斷,其它線(xiàn)程在調(diào)用reader方法,檢測(cè)到flag變量為true,那么便打印變量a的值。此時(shí)控制臺(tái)存在超出期望值的結(jié)果。

(二)new創(chuàng)建對(duì)象

使用關(guān)鍵字new創(chuàng)建對(duì)象時(shí),因其非原子操作,故存在指令重排,指令重排在多線(xiàn)程環(huán)境下會(huì)帶來(lái)負(fù)面影響。

public class Singleton {
    private static UserModel instance;
    
    public static UserModel getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new UserModel(2, "B");
                }
            }
        }
        return instance;
    }
}

@Data
@AllArgsConstructor
class UserModel {
    private Integer userId;
    private String userName;

1、解析創(chuàng)建過(guò)程

  • 使用關(guān)鍵字new創(chuàng)建一個(gè)對(duì)象,大致分為一下過(guò)程:
  • 在??臻g創(chuàng)建引用地址
  • 以類(lèi)文件為模版在堆空間對(duì)象分配內(nèi)存
  • 成員變量初始化
  • 使用構(gòu)造函數(shù)初始化
  • 將引用值賦值給左側(cè)存儲(chǔ)變量

2、重排序過(guò)程分析

針對(duì)上述示例,假設(shè)第一個(gè)線(xiàn)程進(jìn)入synchronized代碼塊,并開(kāi)始創(chuàng)建對(duì)象,由于重排序存在,正常的創(chuàng)建對(duì)象過(guò)程被打亂,可能會(huì)出現(xiàn)在??臻g創(chuàng)建引用地址后,將引用值賦值給左側(cè)存儲(chǔ)變量,隨后因CPU調(diào)度時(shí)間片耗盡而產(chǎn)生中斷的情況。

后續(xù)線(xiàn)程在檢測(cè)到instance變量不為空,則直接使用。因?yàn)閱卫龑?duì)象并為實(shí)例化完成,直接使用會(huì)帶來(lái)意想不到的結(jié)果。

三、應(yīng)對(duì)指令重排

(一)AtomicReference原子類(lèi)

使用原子類(lèi)將一組相關(guān)聯(lián)的變量封裝成一個(gè)對(duì)象,利用原子操作的特性,有效回避指令重排問(wèn)題。

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ValueModel {
    private Integer value;
    private Boolean flag;
}

原子類(lèi)應(yīng)該是解決多線(xiàn)程環(huán)境下指令重排的首選方案,不僅通俗易懂,而且線(xiàn)程間使用的非重量級(jí)互斥鎖,效率相對(duì)較高。

public class E {
    private static final AtomicReference<ValueModel> ar = new AtomicReference<>(new ValueModel());
    
    public static void writer() {
        ar.set(new ValueModel(1, true));
    }
    
    public static void reader() {
        ValueModel valueModel = ar.get();
        if (valueModel.getFlag() != null && valueModel.getFlag()) {
            System.out.println(valueModel.getValue());
            ar.set(new ValueModel(0, false));
        }
    }
}

當(dāng)一組相關(guān)聯(lián)的變量發(fā)生指令重排時(shí),使用原子操作類(lèi)是比較優(yōu)的解法。

(二)volatile關(guān)鍵字

public class Singleton {
    private volatile static UserModel instance;
    
    public static UserModel getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new UserModel(2, "B");
                }
            }
        }
        return instance;
    }
}

@Data
@AllArgsConstructor
class UserModel {
    private Integer userId;
    private String userName;

四、指令重排的理解

1、指令重排廣泛存在

指令重排不僅限于Java程序,實(shí)際上各種編譯器均有指令重排的操作,從軟件到CPU硬件都有。指令重排是對(duì)單線(xiàn)程執(zhí)行的程序的一種性能優(yōu)化,需要明確的是,指令重排在單線(xiàn)程環(huán)境下,不會(huì)改變順序程序執(zhí)行的預(yù)期結(jié)果。

2、多線(xiàn)程環(huán)境指令重排

上面討論了兩種典型多線(xiàn)程環(huán)境下指令重排,分析其帶來(lái)負(fù)面影響,并分別提供了應(yīng)對(duì)方式。

  • 對(duì)于關(guān)聯(lián)變量,先封裝成一個(gè)對(duì)象,然后使用原子類(lèi)來(lái)操作
  • 對(duì)于new對(duì)象,使用volatile關(guān)鍵字修飾目標(biāo)對(duì)象即可

3、synchronized鎖與重排序無(wú)關(guān)

synchronized鎖通過(guò)互斥鎖,有序的保證線(xiàn)程訪(fǎng)問(wèn)特定的代碼塊。代碼塊內(nèi)部的代碼正常按照編譯器執(zhí)行的策略重排序。

盡管synchronized鎖能夠回避多線(xiàn)程環(huán)境下重排序帶來(lái)的不利影響,但是互斥鎖帶來(lái)的線(xiàn)程開(kāi)銷(xiāo)相對(duì)較大,不推薦使用。

synchronized 塊里的非原子操作依舊可能發(fā)生指令重排

到此這篇關(guān)于Java指令重排序在多線(xiàn)程環(huán)境下的應(yīng)對(duì)策略的文章就介紹到這了,更多相關(guān)Java指令重排序內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot中的WebSocketSession原理詳解

    SpringBoot中的WebSocketSession原理詳解

    這篇文章主要介紹了SpringBoot中的WebSocketSession原理詳解,傳統(tǒng)的?HTTP?協(xié)議是無(wú)法支持實(shí)時(shí)通信的,因?yàn)樗且环N無(wú)狀態(tài)協(xié)議,每次請(qǐng)求都是獨(dú)立的,無(wú)法保持連接。為了解決這個(gè)問(wèn)題,WebSocket?協(xié)議被引入,需要的朋友可以參考下
    2023-07-07
  • shiro與spring集成基礎(chǔ)Hello案例詳解

    shiro與spring集成基礎(chǔ)Hello案例詳解

    這篇文章主要介紹了shiro與spring集成基礎(chǔ)Hello案例詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • Java實(shí)現(xiàn)文件監(jiān)控器FileMonitor的實(shí)例代碼

    Java實(shí)現(xiàn)文件監(jiān)控器FileMonitor的實(shí)例代碼

    這篇文章主要介紹了Java實(shí)現(xiàn)文件監(jiān)控器FileMonitor的實(shí)例代碼,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-12-12
  • logback-spring.xml配置詳解

    logback-spring.xml配置詳解

    這篇文章主要介紹了logback-spring.xml詳解,本文介紹了logback-spring.xml相關(guān)的知識(shí)與概念,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-07-07
  • Spring 實(shí)現(xiàn)給Bean屬性注入null值

    Spring 實(shí)現(xiàn)給Bean屬性注入null值

    這篇文章主要介紹了Spring 實(shí)現(xiàn)給Bean屬性注入null值的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • 不調(diào)用方法實(shí)現(xiàn)hutool導(dǎo)出excel圖片示例詳解

    不調(diào)用方法實(shí)現(xiàn)hutool導(dǎo)出excel圖片示例詳解

    這篇文章主要為大家介紹了不調(diào)用方法實(shí)現(xiàn)hutool導(dǎo)出excel圖片示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Springboot+Bootstrap實(shí)現(xiàn)增刪改查實(shí)戰(zhàn)

    Springboot+Bootstrap實(shí)現(xiàn)增刪改查實(shí)戰(zhàn)

    這篇文章主要介紹了Springboot+Bootstrap實(shí)現(xiàn)增刪改查實(shí)戰(zhàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Java實(shí)現(xiàn)數(shù)據(jù)庫(kù)連接池簡(jiǎn)易教程

    Java實(shí)現(xiàn)數(shù)據(jù)庫(kù)連接池簡(jiǎn)易教程

    這篇文章主要為大家介紹了Java實(shí)現(xiàn)數(shù)據(jù)庫(kù)連接池簡(jiǎn)易教程,感興趣的小伙伴們可以參考一下
    2016-01-01
  • SpringBoot中的CompletableFuture類(lèi)詳解

    SpringBoot中的CompletableFuture類(lèi)詳解

    這篇文章主要介紹了SpringBoot中的CompletableFuture類(lèi)詳解,在?Java8中,引入了CompletableFuture類(lèi),它提供了一種簡(jiǎn)單而強(qiáng)大的方式來(lái)執(zhí)行異步任務(wù),今天我們就來(lái)詳細(xì)解讀一下這個(gè)類(lèi),需要的朋友可以參考下
    2023-07-07
  • springboot config 攔截器使用方法實(shí)例詳解

    springboot config 攔截器使用方法實(shí)例詳解

    本文介紹Spring-Boot中使用攔截器的相關(guān)知識(shí),非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧
    2018-05-05

最新評(píng)論

吉林省| 通道| 屏边| 九江市| 桐梓县| 吐鲁番市| 沂水县| 霍城县| 额尔古纳市| 广东省| 新郑市| 灌阳县| 扶风县| 河东区| 武强县| 和龙市| 铁岭县| 敦化市| 沁源县| 台东县| 深水埗区| 阿拉尔市| 五华县| 潜山县| 神农架林区| 乌什县| 宜宾县| 蚌埠市| 文水县| 墨脱县| 正阳县| 松原市| 白玉县| 秦皇岛市| 屏东市| 兖州市| 彭山县| 罗平县| 宝清县| 托克托县| 大城县|