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

Java指令重排在多線程環(huán)境下的解決方式

 更新時間:2022年04月23日 17:31:43   作者:Java知識圖譜  
這篇文章介紹了Java指令重排在多線程環(huán)境下的解決方式,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

一、序言

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

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

二、問題復(fù)原

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

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

public 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ù)測

reader方法僅在flag變量為true時向控制臺打印變量a的值。

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

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

2、指令重排

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

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

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

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

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

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

使用關(guān)鍵字new創(chuàng)建對象時,因其非原子操作,故存在指令重排,指令重排在多線程環(huán)境下會帶來負(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ān)鍵字new創(chuàng)建一個對象,大致分為一下過程:
  • 在??臻g創(chuàng)建引用地址
  • 以類文件為模版在堆空間對象分配內(nèi)存
  • 成員變量初始化
  • 使用構(gòu)造函數(shù)初始化
  • 將引用值賦值給左側(cè)存儲變量

2、重排序過程分析

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

后續(xù)線程在檢測到instance變量不為空,則直接使用。因為單例對象并為實例化完成,直接使用會帶來意想不到的結(jié)果。

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

(一)AtomicReference原子類

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

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

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

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ā)生指令重排時,使用原子操作類是比較優(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程序,實際上各種編譯器均有指令重排的操作,從軟件到CPU硬件都有。指令重排是對單線程執(zhí)行的程序的一種性能優(yōu)化,需要明確的是,指令重排在單線程環(huán)境下,不會改變順序程序執(zhí)行的預(yù)期結(jié)果。

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

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

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

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

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

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

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

到此這篇關(guān)于Java多線程環(huán)境指令重排的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java實現(xiàn)Excel導(dǎo)入導(dǎo)出的步驟詳解

    Java實現(xiàn)Excel導(dǎo)入導(dǎo)出的步驟詳解

    這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)Excel的導(dǎo)入、導(dǎo)出,文中示例代碼介紹的非常詳細(xì),對我們的學(xué)習(xí)或工作有一定的幫助,感興趣的小伙伴們可以參考一下
    2023-06-06
  • Java編程使用卡片布局管理器示例【基于swing組件】

    Java編程使用卡片布局管理器示例【基于swing組件】

    這篇文章主要介紹了Java編程使用卡片布局管理器,結(jié)合實例形式分析了java基于swing組件的卡片布局管理器具體實現(xiàn)與使用技巧,需要的朋友可以參考下
    2018-01-01
  • 淺談關(guān)于Mybatis的mapper-locations配置問題

    淺談關(guān)于Mybatis的mapper-locations配置問題

    MyBatis 是一款優(yōu)秀的半自動的ORM持久層框架,它支持自定義 SQL、存儲過程以及高級映射。MyBatis 免除了幾乎所有的 JDBC 代碼以及設(shè)置參數(shù)和獲取結(jié)果集的工作,需要的朋友可以參考下
    2023-05-05
  • Java中callable的實現(xiàn)原理

    Java中callable的實現(xiàn)原理

    本文主要介紹了Java里的callable的實現(xiàn)原理,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-03-03
  • FeignMultipartSupportConfig上傳圖片配置方式

    FeignMultipartSupportConfig上傳圖片配置方式

    這篇文章主要介紹了FeignMultipartSupportConfig上傳圖片配置方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • springboot 2.x整合mybatis實現(xiàn)增刪查和批量處理方式

    springboot 2.x整合mybatis實現(xiàn)增刪查和批量處理方式

    這篇文章主要介紹了springboot 2.x整合mybatis實現(xiàn)增刪查和批量處理方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • 開源的Java圖片處理庫實例詳解

    開源的Java圖片處理庫實例詳解

    Java?圖片處理庫提供了豐富的功能,用于處理和增強(qiáng)圖像,在Java生態(tài)系統(tǒng)中,有幾個流行的開源庫可以用于圖片處理,這些庫提供了豐富的功能,如圖像縮放、裁剪、顏色調(diào)整、格式轉(zhuǎn)換等,本文介紹開源的Java圖片處理庫介紹,感興趣的朋友一起看看吧
    2024-03-03
  • Java httpclient請求form-data格式并設(shè)置boundary代碼實現(xiàn)方法

    Java httpclient請求form-data格式并設(shè)置boundary代碼實現(xiàn)方法

    在 Java 開發(fā)中,經(jīng)常會遇到需要使用 httpclient 發(fā)送 form-data 格式請求的場景,本文將詳細(xì)介紹如何正確地實現(xiàn)這一操作,包括數(shù)據(jù)格式示例、常見報錯及解決方法,本文通過實例代碼詳解講解,感興趣的朋友一起看看吧
    2025-01-01
  • mybatis plus 關(guān)聯(lián)數(shù)據(jù)庫排除不必要字段方式

    mybatis plus 關(guān)聯(lián)數(shù)據(jù)庫排除不必要字段方式

    這篇文章主要介紹了mybatis plus 關(guān)聯(lián)數(shù)據(jù)庫排除不必要字段方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • 關(guān)于遠(yuǎn)程調(diào)用RestTemplate的使用避坑指南

    關(guān)于遠(yuǎn)程調(diào)用RestTemplate的使用避坑指南

    這篇文章主要介紹了關(guān)于遠(yuǎn)程調(diào)用RestTemplate的使用避坑指南,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10

最新評論

兴仁县| 耒阳市| 大同县| 斗六市| 攀枝花市| 寻乌县| 宾阳县| 怀来县| 峨山| 沾化县| 泽州县| 西宁市| 东丰县| 靖州| 宁安市| 汝南县| 麻城市| 探索| 永定县| 阜平县| 天等县| 兴文县| 本溪市| 弥渡县| 黔西县| 湘阴县| 探索| 鱼台县| 怀宁县| 镇安县| 六盘水市| 尖扎县| 陈巴尔虎旗| 商水县| 全椒县| 兴山县| 内江市| 富锦市| 鄱阳县| 泽库县| 广平县|