JVM-- 先行發生原則


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

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

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

先行發生原則--是判斷是否存在數據競爭、線程是否安全的主要依據。

先行發生是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

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM