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

并發(fā)編程之Java內(nèi)存模型順序一致性

 更新時間:2021年11月04日 09:05:24   作者:李子捌  
這篇文章主要介紹了并發(fā)編程Java內(nèi)存模型順序一致性,順序一致性內(nèi)存模型是一個理論參考模型,處理器的內(nèi)存模型和編程語言的內(nèi)存模型都會以順序一致性內(nèi)存模型作為參照,下面我們一起進入文章看看學校內(nèi)容,需要的朋友可以參考一下

簡介:

順序一致性內(nèi)存模型是一個理論參考模型,處理器的內(nèi)存模型和編程語言的內(nèi)存模型都會以順序一致性內(nèi)存模型作為參照。

1、數(shù)據(jù)競爭和順序一致性

當程序未正確同步時,就可能存在數(shù)據(jù)競爭。

1.1 Java內(nèi)存模型規(guī)范對數(shù)據(jù)競爭的定義

定義如下:

  • 在一個線程中寫一個變量
  • 在另一個線程中讀同一個變量
  • 寫和讀沒有通過同步來排序

如果一個多線程程序能夠正確同步,這個程序?qū)⑹且粋€沒有數(shù)據(jù)競爭的程序,往往存在數(shù)據(jù)競爭的程序,運行結(jié)果與我們的預期結(jié)果都會存在偏差。

1.2 JMM對多線程程序的內(nèi)存一致性做的保證

如果程序正確同步(正確使用synchronized、volatilefinal),程序的執(zhí)行將具有順序一致性(Sequentially Consistent)——即程序的執(zhí)行結(jié)果與該程序在順序一致性內(nèi)存模型中的執(zhí)行結(jié)果相同。

2、順序一致性內(nèi)存模型

2.1 特性

  • 一個線程中的所有操作必須按照程序的執(zhí)行順序來執(zhí)行
  • (不管是否正確同步)所有的線程都只能看到一個單一的操作執(zhí)行順序,每個操作都必須原子執(zhí)行且立刻對所有線程可見。

圖示:順序一致性內(nèi)存模型視圖

在概念上,順序一致性模型有一個單一的全局內(nèi)存,這個內(nèi)存通過一個左右擺動的開關(guān)可以連接到任意一個線程,同時每一個線程必須按照程序的順序來執(zhí)行內(nèi)存的讀/寫操作。上圖中可以看出,在任意時刻最多只有一個線程可以連接到內(nèi)存。因此,在多線程并發(fā)執(zhí)行時,圖中的開關(guān)裝置能把所有的內(nèi)存讀/寫操作串行化(即在順序一致性模型中所有操作之間具有全序關(guān)系)。

2.2 舉例說明順序一致性模型

假設(shè)兩個線程A和B并發(fā)執(zhí)行。其中

A線程的操作在程序中的順序為:A1 - A2 - A3

B線程的操作在程序中的順序為:B1 - B2 - B3。

假設(shè)線程A和線程B使用監(jiān)視器鎖來正確同步,A線程的3個操作執(zhí)行后釋放監(jiān)視器鎖,隨后B線程獲取同一個監(jiān)視器鎖。那么程序在順序一致性模型中的執(zhí)行效果如下所示:順序一致性模型的一種執(zhí)行效果

假設(shè)線程A和線程B沒有做同步,那么這個未同步的程序在順序一致性模型中的另一種可能的效果如下所示:

順序一致性模型的另一種執(zhí)行效果:

未同步程序在順序一致性模型中雖然整體執(zhí)行順序是無序的,但是所有線程都只能看到一個一直的整體執(zhí)行順序。以上圖為例,線程A和B看到的執(zhí)行順序都是:A1 - B1 - A2 - B2 - A3 - B3。之所以能得到這個保證是因為順序一致性內(nèi)存模型中的每個操作必須立即對任意線程可見。

但是,在JMM中就沒有這個保證。未同步程序在JMM中不但整體的執(zhí)行順序是無序的,而且所有線程看到的操作執(zhí)行順序也可能不一致。 比如,在當前線程把寫過的數(shù)據(jù)緩存在本地內(nèi)存中,在沒有刷新到主內(nèi)存之前,這個寫操作僅對當前線程可見;從其他線程的角度來觀察,會認為這個寫操作根本被當前線程執(zhí)行。只有當前線程把本地內(nèi)存中寫過的數(shù)據(jù)刷新到主內(nèi)存之后,這個寫操作才能對其他線程可見。這種情況就會出現(xiàn)多種運行結(jié)果。

2.3 同步程序的順序一致性效果

對上一章的ReorderExample程序用鎖來同步

package com.lizba.p1;

/**
 * <p>
 *      同步示例
 * </p>
 *
 * @Author: Liziba
 * @Date: 2021/6/8 21:44
 */
public class SynReorderExample {

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

    public synchronized void writer() {     // 獲取鎖
        a = 1;
        flag = true;
    }                                       // 釋放鎖

    public synchronized void reader() {     // 獲取鎖
        if (flag) {
            int i = a * a;
            System.out.println("i:" + i);
        }
    }                                       // 釋放鎖

}

測試代碼

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

    final SynReorderExample re = new SynReorderExample();

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

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

執(zhí)行多次結(jié)果結(jié)果都為1

總結(jié):

在上面的示例代碼中,假設(shè)A線程執(zhí)行writer()方法后,B線程執(zhí)行reader()方法。這是一個正確同步的多線程程序。根據(jù)JMM規(guī)范,該程序的執(zhí)行結(jié)果將與該程序在順序一致性內(nèi)存模型中的執(zhí)行結(jié)果相同。

順序一致性模型中和JMM內(nèi)存模型中的執(zhí)行時序圖

總結(jié)

在順序一致性模型中,所有操作完全按程序的順序串行執(zhí)行。而在JMM中,臨界區(qū)內(nèi)的代碼可以重排序(但JMM不允許臨界區(qū)的代碼“逸出”到臨界區(qū)之外,那樣會破壞監(jiān)視器鎖的語義)。JMM會在進入臨界區(qū)和退出臨界區(qū)的關(guān)鍵時間點做一些特殊處理,使得線程在這兩個時間點具有順序一致性模型中相同的內(nèi)存視圖。雖然線程A在臨界區(qū)內(nèi)做了重排序,但由于監(jiān)視鎖互斥執(zhí)行的特性,這里線程B無法“觀察”到線程A在臨界區(qū)內(nèi)的重排序。JMM在具體實現(xiàn)上的基本方針為:在不改變(正確同步)程序執(zhí)行結(jié)果的前提下,盡可能為編譯器和處理器的優(yōu)化打開方便大門。

2.4 未同步程序的執(zhí)行特性

對于未同步或者未正確同步(代碼寫錯了的兄弟們),JMM只提供最小的安全性:

線程執(zhí)行時讀取到的值不會無中生有(Out Of Thin Air)

  • 之前某個線程寫入的值
  • 默認值(0、Null、False)-- JVM會在已經(jīng)清零了內(nèi)存空間(Pre-zeroed Memory)分配對象。

未同步程序在兩個模型中的執(zhí)行特性對比

比較內(nèi)容\模型名稱 順序一致性模型 JMM模型
單線程內(nèi)順序執(zhí)行 ×
一致的操作執(zhí)行順序 ×
64位long型和double型變量寫原子性 ×

第三個差異和總線的機制有關(guān)。在一些32位處理器上,處理64位的數(shù)據(jù)寫操作,需要將一個寫操作拆分為兩個32位的寫操作。

3、 64位long型和double型變量寫原子性

3.1 CPU、內(nèi)存和總線簡述

在計算機中,數(shù)據(jù)通過總線在處理器和內(nèi)存之間傳遞,每次處理器和內(nèi)存之間的數(shù)據(jù)傳遞都是通過一系列的步驟來完成的,這一系列的步驟稱之為總線事務(wù)(Bus Transaction)??偩€事務(wù)包括讀事務(wù)(Read Transaction)和寫事務(wù)(WriteTransaction),事務(wù)會讀\寫內(nèi)存中一個或多個物理上連續(xù)的字。

  • 讀事務(wù) → 內(nèi)存到處理器
  • 寫事務(wù) → 處理器到內(nèi)存

重點:總線會同步試圖并發(fā)使用總線的事務(wù)。在一個處理器執(zhí)行總線事務(wù)期間,總線會禁止其他處理器和I\O設(shè)備執(zhí)行內(nèi)存的讀\寫。

圖示:總線工作機制

由上圖所示:設(shè)處理器A、B、C、D同時向總線發(fā)起總線事務(wù),這時總線總裁(Bus Arbitration)會對競爭作出裁決,這里假設(shè)處理器A在競爭中獲勝(總線仲裁會確保所有處理器能公平訪問內(nèi)存)。此時處理器A繼續(xù)它的總線事務(wù),而其他所有的總線事務(wù)必須要等待A的事務(wù)完成才能再次執(zhí)行內(nèi)存的讀\寫操作。總線事務(wù)工作機制確保處理器對內(nèi)存的訪問以串行的方式執(zhí)行。在任意時間點都只有一個處理器可以訪問內(nèi)存,這個特性能確保總線事務(wù)之間的內(nèi)存讀\寫操作具有原子性。

3.2 long和double類型的操作

在一些32位的處理器上,如果要求對64位數(shù)據(jù)的寫操作具有原子性,那么會有非常大的同步開銷。Java語言規(guī)范中鼓勵但不強求JVM對64位long型和double類型的變量寫操作具有原子性。當JVM在這種處理器上運行時,會把一個64位的變量寫操作拆成兩個32位寫操作來執(zhí)行,此時寫不具備原子性。

圖示:總線事務(wù)執(zhí)行的時序圖

存在問題:

假設(shè)處理器A寫一個long類型的變量,同時處理器B要讀這個long類型的變量。處理器A中64位的寫操作被拆分成兩個32位的寫操作,且這兩個32位的寫操作被分配到不同的事務(wù)中執(zhí)行。此時,處理器B中64位的讀操作被分配到單個讀事務(wù)中執(zhí)行。如果按照上面的執(zhí)行順序,那么處理器B讀取的將會是一個不完整的無效值。

處理方式:

JSR-133內(nèi)存模型開始(JDK1.5),寫操作能拆分成兩個32位寫事務(wù)執(zhí)行,讀操作必須在單個事務(wù)中執(zhí)行。

到此這篇關(guān)于并發(fā)編程之Java內(nèi)存模型順序一致性的文章就介紹到這了,更多相關(guān)Java內(nèi)存模型順序一致性內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Springbean的幾種注入方式都了解嗎

    Springbean的幾種注入方式都了解嗎

    這篇文章主要介紹了Springbean的幾種注入方式都了解嗎,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-01-01
  • java實現(xiàn)TCP socket和UDP socket的實例

    java實現(xiàn)TCP socket和UDP socket的實例

    這篇文章主要介紹了本文主要介紹了java實現(xiàn)TCP socket和UDP socket的實例,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • 淺談Maven Wrapper

    淺談Maven Wrapper

    這篇文章主要介紹了淺談Maven Wrapper,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12
  • 詳解java開發(fā)webservice的幾種方式

    詳解java開發(fā)webservice的幾種方式

    webservice的應(yīng)用已經(jīng)越來越廣泛了,下面介紹幾種在Java體系中開發(fā)webservice的方式,有興趣的可以了解一下。
    2016-11-11
  • 深入淺析java中flyway使用簡介

    深入淺析java中flyway使用簡介

    Flyway是獨立于數(shù)據(jù)庫的應(yīng)用、管理并跟蹤數(shù)據(jù)庫變更的數(shù)據(jù)庫版本管理工具。這篇文章主要介紹了flyway使用簡介,需要的朋友可以參考下
    2020-07-07
  • Java中資源加載的方法及Spring的ResourceLoader應(yīng)用小結(jié)

    Java中資源加載的方法及Spring的ResourceLoader應(yīng)用小結(jié)

    在Java開發(fā)中,資源加載是一個基礎(chǔ)而重要的操作,這篇文章主要介紹了深入理解Java中資源加載的方法及Spring的ResourceLoader應(yīng)用,本文通過實例代碼演示了通過ClassLoader和Class獲取資源的內(nèi)容,以及使用Spring的ResourceLoader加載多個資源的過程,需要的朋友可以參考下
    2024-01-01
  • SpringBoot 集成 Druid過程解析

    SpringBoot 集成 Druid過程解析

    這篇文章主要介紹了SpringBoot 集成 Druid過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-09-09
  • Java實現(xiàn)人機猜拳游戲

    Java實現(xiàn)人機猜拳游戲

    這篇文章主要為大家詳細介紹了Java實現(xiàn)人機猜拳游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • SpringBoot整合MybatisSQL過濾@Intercepts的實現(xiàn)

    SpringBoot整合MybatisSQL過濾@Intercepts的實現(xiàn)

    這篇文章主要介紹了SpringBoot整合MybatisSQL過濾@Intercepts的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-03-03
  • 我對@RestController注解的理解

    我對@RestController注解的理解

    這篇文章主要介紹了我對@RestController注解的理解,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03

最新評論

沙雅县| 韩城市| 张掖市| 宁夏| 漠河县| 突泉县| 杨浦区| 元谋县| 鄂托克旗| 定州市| 监利县| 衡阳县| 新化县| 衡阳县| 阿巴嘎旗| 铜山县| 沾益县| 北川| 清水县| 哈巴河县| 舒城县| 大悟县| 西吉县| 从化市| 循化| 措美县| 松原市| 仁化县| 黄浦区| 康平县| 金塔县| 嘉祥县| 皋兰县| 嘉义县| 贵阳市| 如皋市| 太谷县| 广平县| 玛沁县| 彭山县| 冀州市|