Java 線程執行與變量可見性的 happen-before 關係
什麼是 happen-before 的關係
happen-before 的關係是保證一個線程執行的操做結果對不一樣線程中的另外一個操做可見。app
Happens-before 定義程序中全部操做的部分排序。爲了保證執行操做Y的線程能夠看到操做X的結果(X和Y是否出如今不一樣的線程中),X和Y之間必然存在一個先發生的關係。在沒有happen-before 排序的狀況下在兩個操做之間,JVM能夠根據須要自由從新排序(JIT編譯器優化)。優化
happen-before 的不單單是'時間'中的動做從新排序,並且還保證了對內存的讀寫順序。執行寫入和讀取到內存的兩個線程能夠在時鐘時間方面與其餘操做保持一致,但可能看不到彼此一致的更改(內存一致性錯誤),除非它們有happen-before 關係。spa
如何創建 happen-before 關係?
如下是發生以前的規則:線程
- 單線程規則:單個線程中的每一個操做都發生在該程序順序中稍後出現的該線程中的每一個操做以前。
- 監視器鎖定規則:監視器鎖定(退出同步方法/塊)上的解鎖發生 - 在每次後續獲取同一監視器鎖定以前。
- 易失性變量規則:在對該相同字段的每次後續讀取以前發生對易失性字段的寫入。易失性字段的寫入和讀取具備與進入和退出監視器(讀取和寫入時的同步塊)相似的內存一致性效果,但實際上沒有獲取監視器/鎖定。
- 線程啓動規則:線程上的 Thread.start() 調用發生在啓動線程中的每一個操做以前。假設線程A經過調用threadA.start() 生成一個新線程B. 在線程B的run方法中執行的全部操做都將看到線程A調用threadA.start() 方法,以前(僅在線程A中)發生在它們以前。
- 線程鏈接規則:線程中的全部操做都發生在任何其餘線程從該線程上的鏈接成功返回以前。假設線程A經過調用threadA.start() 生成一個新線程B,而後調用threadA.join() 。線程A將在 join() 調用時等待,直到線程B的run方法完成。在join方法返回後,線程A中的全部後續操做都將看到線程B的run方法中執行的全部操做都發生在它們以前。
- 傳遞性:若是A發生在B以前,B發生在C以前,那麼A發生在C以前。