中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JMM中happens-before的原理和使用方法

發布時間:2021-06-25 09:58:19 來源:億速云 閱讀:140 作者:chen 欄目:大數據

這篇文章主要介紹“JMM中happens-before的原理和使用方法”,在日常操作中,相信很多人在JMM中happens-before的原理和使用方法問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”JMM中happens-before的原理和使用方法”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

在JMM中有一個很重要的概念對于我們了解JMM有很大的幫助,那就是happens-before規則。happens-before規則非常重要,它是判斷數據是否存在競爭、線程是否安全的主要依據。JSR-133S使用happens-before概念闡述了兩個操作之間的內存可見性。在JMM中,如果一個操作的結果需要對另一個操作可見,那么這兩個操作則存在happens-before關系。

那什么是happens-before呢?在JSR-133中,happens-before關系定義如下:

  1. 如果一個操作happens-before另一個操作,那么意味著第一個操作的結果對第二個操作可見,而且第一個操作的執行順序將排在第二個操作的前面。

  2. 兩個操作之間存在happens-before關系,并不意味著Java平臺的具體實現必須按照happens-before關系指定的順序來執行。如果重排序之后的結果,與按照happens-before關系來執行的結果一致,那么這種重排序并不非法(也就是說,JMM允許這種重排序)

happens-before規則如下:

  1. 程序順序規則:一個線程中的每一個操作,happens-before于該線程中的任意后續操作。

  2. 監視器規則:對一個鎖的解鎖,happens-before于隨后對這個鎖的加鎖。

  3. volatile規則:對一個volatile變量的寫,happens-before于任意后續對一個volatile變量的讀。

  4. 傳遞性:若果A happens-before B,B happens-before C,那么A happens-before C。

  5. 線程啟動規則:Thread對象的start()方法,happens-before于這個線程的任意后續操作。

  6. 線程終止規則:線程中的任意操作,happens-before于該線程的終止監測。我們可以通過Thread.join()方法結束、Thread.isAlive()的返回值等手段檢測到線程已經終止執行。

  7. 線程中斷操作:對線程interrupt()方法的調用,happens-before于被中斷線程的代碼檢測到中斷事件的發生,可以通過Thread.interrupted()方法檢測到線程是否有中斷發生。

  8. 對象終結規則:一個對象的初始化完成,happens-before于這個對象的finalize()方法的開始。

以上8條happens-before規則都比較簡單,這里LZ只分析第3條volatile變量規則,分析如下:

JMM中happens-before的原理和使用方法

從上圖中,我們看到存在4條happens-before關系,它們分別如下:

  • 1 happens-before 2 和 3 happens-before 4 是有由程序順序性規則產生的。

  • 2 happens-before 3 是由volatile規則產生的。上面提到過,一個volatile變量的讀,總能看到之前對這個volatile變量的寫入。

  • 1 happens-before 4 是由傳遞性規則產生的。

讀到這里,可能很多童鞋會把happens-before理解為“時間上的先后順序”,在這里LZ特別強調happens-hefore不能理解為“時間上的先后順序”,下面LZ用一段代碼解釋寫happens-before和“時間上的先后順序”的不同,代碼如下:

public class VolatileTest4 {
    private int a = 0;
    public int getA() {
        return a;
    }
    public void setA(int a) {
        this.a = a;
    }
}

上面代碼就是一組簡單的setter/getter方法,現在假設現在有兩個線程A和B,線程A先(這里指時間上的先執行)執行setA(10),然后線程B訪問同一個對象的getA()方法,那么此時線程B收到的返回值是對少呢?

答案是:不確定

我們來一次分析下happens-before的各項原則:

  1. 這里兩個方法分別是在兩個線程中被調用,不在一個線程中,這里程序順序性就不適用了

  2. 代碼中沒有同步快,所有監視器規則也不適用

  3. 代碼中變量a是一個普通變量,所以volatile規則也不適用

  4. 后面的線程啟動、中斷、終止和對象的終結和這里完全沒有關系,因此這些規則也是不適用的

  5. 沒有一條happens-before適用,因此傳遞性規則也不適用

在這里,雖然線程A在時間上先于線程B執行,但是由于代碼完全不適用happens-before規則,因此我們無法確定先B收到的值時多少。也就是說上面代碼是線程不安全的。

對于上面代碼,那我們如何修復線程不安全這個問題呢?這里,我們只要滿足happens-before規則中2、3的任意一種規則就可以了。即要么把setter/getter方法定義為synchronized方法,要么在變量a上加volatile修飾符。

通過上面的例子,我們可以得出結論:一個操作“時間上的先發生”不代表這個操作會happens-before其它操作。那一個操作happens-before其它操作,是否就表示這個操作是“時間上先發生”的呢?答案也是否定的,我們來看看下面一個示例:

int i = 1;
int m = 2;

上面兩個賦值操作在同一個線程中,根據程序順序性規則,“int i = 1;"這個操作happens-before ”int m = 2;“這個操作,但是”int m = 2;“這個操作完全有可能被處理器先執行,這并不影響happens-before原則的正確性。因為這種重排序在JMM中是允許的。

最后我們得出的結論是:時間先后順序與happens-before原則之間基本沒有太大的關系,所以我們在衡量并發安全問題的時候不要受到時間順序的干擾,一切必須以happens-before原則為準。 

到此,關于“JMM中happens-before的原理和使用方法”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

jmm
AI

彰化县| 泸定县| 洮南市| 阳山县| 南召县| 云梦县| 荔浦县| 丽水市| 虎林市| 华阴市| 汤阴县| 佛教| 长寿区| 石嘴山市| 绥芬河市| 梓潼县| 云林县| 台前县| 华宁县| 叙永县| 拉萨市| 鸡东县| 收藏| 尉氏县| 江城| 石阡县| 松潘县| 永靖县| 葵青区| 资阳市| 会东县| 台北市| 马龙县| 齐齐哈尔市| 香格里拉县| 泰安市| 乌兰察布市| 沅江市| 山西省| 青田县| 高青县|