Happens-beofre 先行發生原則(JVM 規範)

如果JMM中所有的有序性都只靠volatile和synchronized,那麼有一些操作將會變得很繁瑣,但我們在編寫Java併發代碼時並沒有感到這一點,這是因爲Java語言中有一個先行發生(Happen-Before)原則

這個原則非常重要,它是判斷數據是否存在競爭,線程是否安全的主要依賴。

先行發生原則

指的是JMM中定義的兩項操作之間的依序關係

happens- before關係 主要用於強調兩個有衝突的動作之間的順序,以及定義數據爭用的發生時機

如果說操作A先行發生於操作B,就是在說發生B前,A產生的影響能被B觀察到,“影響”包含了修改內存中共享變量的值、發送了消息、調用了方法等。意味着什麼呢?如下例:

//線程A中執行  
i = 1;  

//線程B中執行  
j = i;  

//線程C中執行  
i = 2;

下面是JMM下一些”天然的“先行發生關係,無須任何同步器協助就已經存在,可以在編碼中直接使用
如果兩個操作之間的關係不在此列,並且無法從下列規則推導出來的話,它們就沒有順序性保障,虛擬機可以對它們進行隨意地重排序

具體的虛擬機實現,有必要確保以下

八大原則

  • 程序次序規則(Pragram Order Rule)
    在一個線程內,按照代碼順序,書寫在前面的操作先行發生於書寫在後面的操作。準確地說應該是控制流順序而不是程序代碼順序,因爲要考慮分支、循環結構。
  • 對象鎖(監視器鎖)法則(Monitor Lock Rule )
    某個 管程(也叫做對象鎖,監視器鎖) 上的unlock動作happens-before同一個管程上後續的lock動作 。這裏必須強調的是同一個鎖,而”後面“是指時間上的先後。
  • volatile變量規則(Volatile Variable Rule)
    對某個volatile字段的寫操作happens- before每個後續對該volatile字段的讀操作,這裏的”後面“同樣指時間上的先後順序。
  • 線程啓動規則(Thread Start Rule)
    在某個線程對象 上調用start()方法happens- before該啓動了的線程中的任意動作
  • 線程終止規則(Thread Termination Rule)
    某線程中的所有操作都先行發生於對此線程的終止檢測,我們可以通過Thread.join()方法結束(任意其它線程成功從該線程對象上的join()中返回),Thread.isAlive()的返回值等作段檢測到線程已經終止執行。
  • 線程中斷規則(Thread Interruption Rule)
    對線程interrupt()方法的調用先行發生於被中斷線程的代碼檢測到中斷事件的發生,可以通過Thread.interrupted()方法檢測是否有中斷髮生
  • 對象終結規則(Finalizer Rule)
    一個對象初始化完成(構造方法執行完成)先行發生於它的finalize()方法的開始
  • 傳遞性(Transitivity)
    如果操作A先行發生於操作B,操作B先行發生於操作C,那就可以得出操作A先行發生於操作C的結論

一個操作”時間上的先發生“不代表這個操作會是”先行發生“,那如果一個操作”先行發生“是否就能推導出這個操作必定是”時間上的先發生“呢?也是不成立的,一個典型的例子就是指令重排序
所以時間上的先後順序與先行發生原則之間基本沒有什麼關係,所以衡量併發安全問題一切必須以先行發生原則爲準。

上面八條是原生Java滿足Happens-before關係的規則,但是我們可以對他們進行推導出

其他滿足happens-before的案例

  • 將一個元素放入一個線程安全的隊列的操作Happens-Before從隊列中取出這個元素的操作
  • 將一個元素放入一個線程安全容器的操作Happens-Before從容器中取出這個元素的操作
  • 在CountDownLatch上的倒數操作Happens-Before CountDownLatch#await()操作
  • Semaphore:release許可的操作Happens-Before acquire許可 的操作
  • CyclicBarrier:線程中調用 await() 之前的操作 happen-before 那些是屏障操作的一部份的操作,後者依次 happen-before 緊跟在從另一個線程中對應 await() 成功返回的操作。
  • Future表示的任務的所有操作Happens-Before Future#get()操作
  • 向Executor提交一個Runnable或Callable的操作Happens-Before任務開始執行操作
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章