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

Java并發(fā)編程之Volatile變量詳解分析

 更新時間:2021年10月29日 11:30:11   作者:該用戶快成仙了  
Volatile關(guān)鍵字是Java提供的一種輕量級的同步機(jī)制,本篇文章深入淺出的講講Java并發(fā)編程的Volatile,通讀本篇對大家的學(xué)習(xí)或工作具有一定的價值,需要的朋友可以參考下

Volatile關(guān)鍵字是Java提供的一種輕量級的同步機(jī)制。Java 語言包含兩種內(nèi)在的同步機(jī)制:同步塊(或方法)和 volatile 變量, 相比synchronized(synchronized通常稱為重量級鎖),volatile更輕量級,因為它不會引起線程上下文的切換和調(diào)度。 但是volatile 變量的同步性較差(有時它更簡單并且開銷更低),而且其使用也更容易出錯。

一、volatile變量的特性

1.1、保證可見性,不保證原子性

  • 當(dāng)寫一個volatile變量時,JMM會把該線程本地內(nèi)存中的變量強(qiáng)制刷新到主內(nèi)存中去;
  • 這個寫會操作會導(dǎo)致其他線程中的volatile變量緩存無效。

來看一段代碼:

public class Test {
    public static void main(String[] args) {
        WangZai wangZai = new WangZai();
        wangZai.start();
        for(; ;){
            if(wangZai.isFlag()){
                System.out.println("hello");
            }
        }
    }
 
    static class WangZai extends Thread {
 
        private boolean flag = false;
 
        public boolean isFlag(){
            return flag;
        }
 
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            flag = true;
            System.out.println("flag = " + flag);
        }
    }
}

你會發(fā)現(xiàn),永遠(yuǎn)都不會輸出hello這一段代碼,按道理線程改了flag變量,主線程也能訪問到的呀?

但是將flag變量用volatile修飾一下,就能輸出hello這段代碼

private volatile boolean flag = false;

每個線程操作數(shù)據(jù)的時候會把數(shù)據(jù)從主內(nèi)存讀取到自己的工作內(nèi)存,如果他操作了數(shù)據(jù)并且寫會了,那其他已經(jīng)讀取的線程的變量副本就會失效了,需要對數(shù)據(jù)進(jìn)行操作又要再次去主內(nèi)存中讀取了。

volatile保證不同線程對共享變量操作的可見性,也就是說一個線程修改了volatile修飾的變量,當(dāng)修改寫回主內(nèi)存時,另外一個線程立即看到最新的值。

1.2、禁止指令重排

重排序需要遵守一定規(guī)則:

  • 重排序操作不會對存在數(shù)據(jù)依賴關(guān)系的操作進(jìn)行重排序。
  • 重排序是為了優(yōu)化性能,但是不管怎么重排序,單線程下程序的執(zhí)行結(jié)果不能被改變。

什么是重排序?

為了提高性能,編譯器和處理器常常會對既定的代碼執(zhí)行順序進(jìn)行指令重排序。

重排序的類型有哪些呢?

深入淺出談?wù)凧ava并發(fā)編程:Volatile

一個好的內(nèi)存模型實際上會放松對處理器和編譯器規(guī)則的束縛,也就是說軟件技術(shù)和硬件技術(shù)都為同一個目標(biāo),而進(jìn)行奮斗:在不改變程序執(zhí)行結(jié)果的前提下,盡可能提高執(zhí)行效率。

JMM對底層盡量減少約束,使其能夠發(fā)揮自身優(yōu)勢。

因此,在執(zhí)行程序時,為了提高性能,編譯器和處理器常常會對指令進(jìn)行重排序。

一般重排序可以分為如下三種:

  • 編譯器優(yōu)化的重排序。編譯器在不改變單線程程序語義的前提下,可以重新安排語句的執(zhí)行順序;
  • 指令級并行的重排序?,F(xiàn)代處理器采用了指令級并行技術(shù)來將多條指令重疊執(zhí)行。如果不存在數(shù)據(jù)依賴性,處理器可以改變語句對應(yīng)機(jī)器指令的執(zhí)行順序;
  • 內(nèi)存系統(tǒng)的重排序。由于處理器使用緩存和讀/寫緩沖區(qū),這使得加載和存儲操作看上去可能是在亂序執(zhí)行的。

那 Volatile 是怎么保證不會被執(zhí)行重排序的呢?

二、內(nèi)存屏障

java編譯器會在生成指令系列時在適當(dāng)?shù)奈恢脮迦雰?nèi)存屏障指令來禁止特定類型的處理器重排序。

為了實現(xiàn)volatile的內(nèi)存語義,JMM會限制特定類型的編譯器和處理器重排序,JMM會針對編譯器制定volatile重排序規(guī)則表:

是否能重排序第二個操作第一個操作普通讀/寫volatile讀volatile寫普通讀/寫NOvolatile讀NONONOvolatile寫NONO

舉例來說,第三行最后一個單元格的意思是:在程序順序中,當(dāng)?shù)谝粋€操作為普通變量的讀或?qū)憰r,如果第二個操作為volatile寫,則編譯器不能重排序這兩個操作。

從上表我們可以看出:

  • 當(dāng)?shù)诙€操作是volatile寫時,不管第一個操作是什么,都不能重排序。這個規(guī)則確保volatile寫之前的操作不會被編譯器重排序到volatile寫之后。
  • 當(dāng)?shù)谝粋€操作是volatile讀時,不管第二個操作是什么,都不能重排序。這個規(guī)則確保volatile讀之后的操作不會被編譯器重排序到volatile讀之前。
  • 當(dāng)?shù)谝粋€操作是volatile寫,第二個操作是volatile讀時,不能重排序。

需要注意的是:volatile寫是在前面和后面分別插入內(nèi)存屏障,而volatile讀操作是在后面插入兩個內(nèi)存屏障。

深入淺出談?wù)凧ava并發(fā)編程:Volatile

深入淺出談?wù)凧ava并發(fā)編程:Volatile

從JDK5開始,提出了happens-before的概念,通過這個概念來闡述操作之間的內(nèi)存可見性。

三、happens-before

happens-before 關(guān)系的定義:

  • 如果一個操作 happens-before 另一個操作,那么第一個操作的執(zhí)行結(jié)果就會對第二個操作可見。
  • 兩個操作之間如果存在 happens-before 關(guān)系,并不意味著 Java 平臺的具體實現(xiàn)就必須按照 happens-before 關(guān)系指定的順序來執(zhí)行。如果重排序之后的執(zhí)行結(jié)果,與按照 happens-before 關(guān)系來執(zhí)行的結(jié)果一直,那么 JMM 也允許這樣的重排序。

看到這兒,你是不是覺得,這個怎么和 as-if-serial 語義一樣呢。沒錯, happens-before 關(guān)系本質(zhì)上和 as-if-serial 語義是一回事。

as-if-serial 語義保證的是單線程內(nèi)重排序之后的執(zhí)行結(jié)果和程序代碼本身應(yīng)該出現(xiàn)的結(jié)果是一致的,

happens-before 關(guān)系保證的是正確同步的多線程程序的執(zhí)行結(jié)果不會被重排序改變。

一句話來總結(jié)就是:如果操作 A happens-before 操作 B ,那么操作 A 在內(nèi)存上所做的操作對操作 B 都是可見的,不管它們在不在一個線程。

在 Java 中,對于 happens-before 關(guān)系,有以下規(guī)定:

  • 程序順序規(guī)則:一個線程中的每一個操作, happens-before 于該線程中的任意后續(xù)操作。
  • 監(jiān)視器鎖規(guī)則:對一個鎖的解鎖, happens-before 于隨后對這個鎖的加鎖。
  • volatile 變量規(guī)則:對一個 volatile 域的寫, happens-before 與任意后續(xù)對這個 volatile 域的讀。
  • 傳遞性:如果 A happens-before B , 且 B happens-before C ,那么 A happens-before C。
  • start 規(guī)則:如果線程 A 執(zhí)行操作 ThreadB。start() 啟動線程 B ,那么 A 線程的 ThreadB。start() 操作 happens-before 于線程 B 中的任意操作。
  • join 規(guī)則:如果線程 A 執(zhí)行操作 ThreadB。join() 并成功返回,那么線程 B 中的任意操作 happens-before 于線程 A 從 ThreadB。join() 操作成功返回。

到此這篇關(guān)于Java并發(fā)編程之Volatile變量詳解分析的文章就介紹到這了,更多相關(guān)Java Volatile變量內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • IDEA2019.3配置Hibernate的詳細(xì)教程(未使用IDEA的自動化)

    IDEA2019.3配置Hibernate的詳細(xì)教程(未使用IDEA的自動化)

    這篇文章主要介紹了IDEA2019.3配置Hibernate的詳細(xì)教程,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • java對ArrayList排序代碼示例

    java對ArrayList排序代碼示例

    本文通過代碼示例給大家介紹java對arraylist排序,代碼簡潔易懂,感興趣的朋友一起學(xué)習(xí)吧
    2015-11-11
  • Java Swing實現(xiàn)餐廳點餐系統(tǒng)源碼(收藏版)

    Java Swing實現(xiàn)餐廳點餐系統(tǒng)源碼(收藏版)

    這篇文章主要介紹了Java Swing實現(xiàn)餐廳點餐系統(tǒng)源碼,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-02-02
  • 解決myBatis generator逆向生成沒有根據(jù)主鍵的select,update和delete問題

    解決myBatis generator逆向生成沒有根據(jù)主鍵的select,update和delete問題

    這篇文章主要介紹了解決myBatis generator逆向生成沒有根據(jù)主鍵的select,update和delete問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • IDEA常用插件之代碼掃描SonarLint詳解

    IDEA常用插件之代碼掃描SonarLint詳解

    SonarLint是一款用于代碼掃描的插件,可以幫助查找隱藏的bug,下載并安裝插件后,右鍵點擊項目并選擇“Analyze”、“AnalyzewithSonarLint”,掃描完成后可以在下方查看報告
    2025-01-01
  • java集合——Java中的equals和hashCode方法詳解

    java集合——Java中的equals和hashCode方法詳解

    本篇文章詳細(xì)介紹了Java中的equals和hashCode方法詳解,Object 類是所有類的父類,非常具有實用價值,需要的朋友可以參考下。
    2016-10-10
  • SpringBoot實現(xiàn)動態(tài)多線程并發(fā)定時任務(wù)

    SpringBoot實現(xiàn)動態(tài)多線程并發(fā)定時任務(wù)

    這篇文章主要為大家詳細(xì)介紹了SpringBoot實現(xiàn)動態(tài)多線程并發(fā)定時任務(wù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • mybatis的selectKey作用詳解

    mybatis的selectKey作用詳解

    這篇文章主要介紹了mybatis的selectKey作用詳解,具有很好的參考價值,希望對大家有所幫助。以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。</P><P>
    2022-01-01
  • Spring Cloud Zuul添加過濾器過程解析

    Spring Cloud Zuul添加過濾器過程解析

    這篇文章主要介紹了Spring Cloud Zuul添加過濾器過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-12-12
  • Springcloud RestTemplate服務(wù)調(diào)用代碼實例

    Springcloud RestTemplate服務(wù)調(diào)用代碼實例

    這篇文章主要介紹了Springcloud RestTemplate服務(wù)調(diào)用代碼實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-08-08

最新評論

阳泉市| 大同县| 镶黄旗| 田阳县| 翁牛特旗| 铜梁县| 裕民县| 镇巴县| 黄浦区| 余干县| 娄底市| 赤水市| 肥城市| 抚顺县| 白玉县| 英吉沙县| 岑溪市| 剑川县| 乐山市| 江阴市| 八宿县| 大渡口区| 凤城市| 凯里市| 五河县| 丹寨县| 平邑县| 清新县| 隆子县| 慈溪市| 驻马店市| 岳西县| 青田县| 太仆寺旗| 年辖:市辖区| 卫辉市| 陵川县| 阿克苏市| 资讯 | 阜宁县| 安新县|