1. 程式人生 > 其它 >JMM(JAVA記憶體模型) - 先行發生原則

JMM(JAVA記憶體模型) - 先行發生原則

技術標籤:jvmjvmjava多執行緒併發

本文中需要的基礎知識:指令重排

執行緒中兩個非常重要的問題就是:原子性與可見性.

而下面的先行發生原則就是用來解決可見性問題的.

先行發生原則--是判斷是否存在資料競爭、執行緒是否安全的主要依據。

先行發生是Java記憶體模型中定義的兩項操作之間的偏序關係。如果說操作A先行發生於操作B,其實就是說在發生操作B之前,操作A產生的影響被操作B察覺。

以下面的一段虛擬碼為例:

//以下操作線上程A中執行
int i = 1;

//以下操作線上程B中執行
j = i;

//以下操作線上程C中執行
i = 2

由於執行緒執行的先後順序不同,會導致最後j 的結果出現差異。若使執行緒安全,那麼A先行發生B,B先行發生C。

執行緒B可能獲取的是一些過期的資料。故執行緒不安全!

但是在Java記憶體模型中確實存在一些已經存在的先行發生關係,這些先行發生關係不需要任何的同步操作,就可以保證其執行緒安全!

1、程式次序規則在一個執行緒內,書寫在前面的程式碼先行發生於後面的。確切地說應該是,按照程式的控制流順序,因為存在一些分支結構。

2、Volatile變數規則對一個volatile修飾的變數,對他的寫操作先行發生於讀操作。

3、執行緒啟動規則。Thread物件的start()方法先行發生於此執行緒的每一個動作。

4、執行緒終止規則。執行緒的所有操作都先行發生於對此執行緒的終止檢測。

5、執行緒中斷規則。對執行緒interrupt()方法的呼叫先行發生於被中斷執行緒的程式碼所檢測到的中斷事件。

6、物件終止規則。一個物件的初始化完成(建構函式之行結束)先行發生於發的finilize()方法的開始。

7、傳遞性A先行發生B,B先行發生C,那麼,A先行發生C。

8、管程鎖定規則。一個unlock操作先行發生於後面對同一個鎖的lock操作。

以上就是Java無需任何的同步手段就能成立的先行發生規則。其他情況下就沒有順序保障,虛擬機器可以對它們隨意地進行重排序。

總結:

  happens-before指的是前面發生的操作的結構對於後面的操作的結果都是可見的,而在真正操作中並不一定前面的操作就先進行.

執行E的時候,E是不是保證看見C呢?
由法則1,hb(D,E)
由法則8,hb(B,D)

由法則1,hb(A,B)
綜上可以推出,hb(A, E),但是推不出hb(C, E)
所以,E不一定能看見C,但是E一定能看見A,所以執行E的時候,有可能thread2看到的x的值還是1