先行發生關係(happens-before)

分三個層次吧:

第一層次:單個對象或單個方法層次

a.程序次序規則:可以理解爲某一線程中的run方法執行代碼,控制流書寫在前的一定先行於書寫在後的,當然,是廣義的書寫,考慮循環及判斷

b.管程鎖定規則:可以理解爲被鎖的(比如synchronized鎖定的)程序塊中,執行時間在前的先行於執行時間在後的

c.volatile規則:對一個volatile的寫執行先行於時間上位於後面的對這個變量的讀操作

d.對象的構造方法先行於finalize的開始

注意:a指的是書寫次序、b和c指的是時間次序,這個是不一樣的,a指單線程內,而b和c可以看作不同線程內執行的時間前後

 

第二層次:線程層次:

e.線程啓動先行於線程內的執行

f.線程執行先行於線程終止

g.對線程interrupt()方法的調用先行於中斷事件的發生

 

第三個層次:傳遞原則:

若A先行於B,B先行於C,則A先行於C

 

符合先行發生關係的邏輯由系統保證多線程的邏輯同步,不需要自己控制

 

有一個注意點:先行發生關係並不是CPU指令集上的前後順序,或者說並非實際執行的先後順序。怎麼理解呢?符合先行發生關係的邏輯:A先行於B,以Java爲例,JVM保證若B用到了A的數值或結果,則該數值或結果,A一定先行於B,若A、B並無必然的聯繫,從JVM層面,A、B甚至是可以互換的。再舉一個例子可能更好理解一些:代碼的書寫次序:

    {

        int a = 1; //A

        int b = 2; //B

        int c = a + b; //C

    }

A先行於C,B也先行於C,A、B並無必然的次序,在字節碼層面,執行的次序可能爲A->B->C,也可能是B->A->C

在理想的內存模型中,一定是A->B->C,但JVM爲了運行優化,可能會對A、B進行交換。

有一個辦法可以阻止A、B換位:volatile關鍵字--被volatile修飾的變量,讀不與前交換,寫不與後交換

在單線程的環境下,A、B換位並不會影響程序運行結果,而在多線程的環境下,因A、B換位可能會引發一些非所期望的結果,要加倍關注。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章