Java記憶體模型

來源:互聯網
上載者:User

標籤:模型   before   執行   特定   斷線   數組   變數   改變   int   

多線程如何通訊,同步?

1)通訊: 共用記憶體/訊息佇列

2)同步: 訪問時加鎖/訊息佇列

JMM採用共用記憶體以及訪問時加鎖。JMM決定一個線程對變數的寫入何時對另一個線程可見。

Java中,靜態變數/執行個體變數/數組元素都分配在堆中,而局部變數/方法參數/異常變數分配在棧中。線程共用堆,但是專屬棧。所以棧不存在共用可見度問題。

每個線程有自己的工作記憶體,可能是緩衝/寫緩衝區/寄存器等。線程間通訊時,線程A先寫到工作記憶體,再重新整理到主記憶體;然後線程B從主記憶體讀取最新資料到工作記憶體並棄置站台。由於存在重排序,所以結果可能有所不同。

重排序:

1)編譯器最佳化的重排序: 改變代碼執行順序

2)處理器最佳化的重排序:指令級並行技術(ILP),能並發執行多條指令,改變執行順序

3)記憶體重排序: 由於用緩衝和讀寫緩衝區,使得load和store可能亂序執行

JMM的編譯器會禁止特定類型的編譯器重排序,JMM的處理器通過插入記憶體屏障(Load/Load, Load/Store, Store/Load, Store/Store)禁止特定類型的處理器重排序。

如果一個操作對另一個操作存在可見度,必須滿足happens-before規則。如果兩個操作缺乏happens-before關係,JVM可以任意重排序。

happens-before規則:

1)程式規則:之前的代碼先於後面的代碼執行

2)鎖規則: unlock先於lock執行

3)volatile規則: 寫入先於讀取執行

4)線程啟動規則:Thread.start()優於所有後續動作執行

5)線程終止規則: 線程中所有動作必須先於其它線程檢測到該線程結束執行

6)線程中斷規則: 當一個線程在另一個線程上調用interrupt,必須在被中斷線程檢測到interrupt之前執行

7)終結器規則: 對象的建構函式必須在啟動該對象的終結器之前執行完成。

8)路由規則: A happens-before B, B happens-before C -> A happens-before C

 

volatile, synchronized, Lock, final能保證記憶體可見度。volatile變數每次從主記憶體load資料,synchronized和Lock在開始的時候將記憶體資料copy到工作記憶體,結束的時候將工作記憶體的資料refresh到主記憶體。final變數一旦初始化完,對其他線程立即可見。

volatile, synchronized能保證有序性。volatile通過插入記憶體屏障禁止重排序,synchronized通過每次只允許一個線程對一個變數加鎖。

Java記憶體模型

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.