java_JMM_【happens-before】

(1)多線程共享變量

實例域,靜態域和數組元素都是放在堆內存中(所有線程均可訪問到,是可以共享的)

局部變量,方法定義參數和異常處理器參數不會在線程間共享

(2)JMM結構模型

1. 線程A將主內存共享變量讀取讀入線程A的工作內存後並進行操作,之後將數據重  新寫回到主內存中

2. 線程B從主存中讀取最新的共享變量

如果線程A更新後沒有及時寫會主內存而此時線程B讀到的是過期的數據出現了“髒讀”現象

可以通過同步機制或者volatile關鍵字讓共享變量強制刷新到內存 變量具有可見性

 

(2)重排序

爲了提高性能,編譯器和處理器常常會對指令進行重排序

  1. 編譯器優化的重排序。
  2. 指令級並行的重排序
  3. 內存系統的重排序

as-if-serial不管怎麼重排序(編譯器和處理器爲了提供並行度)(單線程)程序的執行結果不能被改變。

  1. volatile保持內存可見性和防止指令重排序

(3)happens-before

JMM可以通過happens-before關係向程序員提供跨線程的內存可見性保證

如果A線程的寫操作a

B線程的讀操作b

存在happens-before關係,儘管a操作和b操作在不同的線程中執行,但JMM向程序員保證a操作將對b操作可見

  1. 如果一個操作happens-before另一個操作,那麼第一個操作的執行結果將對第二個操作可見,而且第一個操作的執行順序排在第二個操作之前。
  2. 兩個操作之間存在happens-before關係,並不意味着Java平臺的具體實現必須要按照happens-before關係指定的順序來執行。

as-if-serial

happens-before

單線程內程序的執行結果不被改變

多線程程序的執行結果不被改變。

儘可能單線程程序是按程序的順序來執行的

儘可能正確同步的多線程程序是按happens-before指定的順序來執行的。

  1. as-if-serial語義和happens-before這麼做的目的,都是爲了在不改變程序執行結果的前提下,儘可能地提高程序執行的並行度。

(4)happens-before具體規則

·  程序順序規則:一個線程中的每個操作,happens-before於該線程中的任意後續操作。

·  監視器鎖規則:對一個鎖的解鎖,happens-before於隨後對這個鎖的加鎖。

·  volatile變量規則:對一個volatile域的寫,happens-before於任意後續對這個volatile域的讀。

·  傳遞性:如果A happens-before B,且B happens-before C,那麼A happens-before C。

·  start()規則:如果線程A執行操作ThreadB.start()(啓動線程B),那麼A線程的ThreadB.start()操作happens-before於線程B中的任意操作。

·  join()規則:如果線程A執行操作ThreadB.join()併成功返回,那麼線程B中的任意操作happens-before於線程A從ThreadB.join()操作成功返回。

·  程序中斷規則:對線程interrupted()方法的調用先行於被中斷線程的代碼檢測到中斷時間的發生。

·  對象finalize規則:一個對象的初始化完成(構造函數執行結束)先行於發生它的finalize()方法的開始。

  1. 總結

 

  1. 對於會改變程序執行結果的重排序,JMM要求編譯器和處理器必須禁止這種重排序。
  2. 對於不會改變程序執行結果的重排序,JMM對編譯器和處理器不做要求(JMM允許這種 重排序)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章