1. 程式人生 > >記憶體可見性和happens-before原則

記憶體可見性和happens-before原則

java-記憶體可見性

1.什麼是記憶體可見性?

首先我們看下面這張圖
在這裡插入圖片描述
java的執行機制來說,會為每個執行緒建立一個棧,執行緒執行的時候就會優先讀取自己的工作記憶體內部的資料。然後線上程執行之後把資料在寫會到主記憶體裡面。但是多執行緒的條件下,可能會出現上一個執行緒還沒有執行完的情況下,這個執行緒就要操作這個資料了,這個時候就會出現本執行緒去記憶體讀到的資料和上一個執行緒內部的資料是不一致的。那麼該如何保證一個數據在多執行緒之間是相同的呢?這就是記憶體可見性。

2.描述記憶體可見性的規則 happens-before 規則

簡單來說就是如何A操作的結果是對B操作可見的,那麼就必然存在A happens-before B的關係。注意他指的不是執行時間的先後而是可見性的先後順序。java為了描述這種記憶體可見性的規則就提出了happens-before規則。

3.java裡面一些天然存在的happens-before關係

程式次序原則: 在一個執行緒內,程式碼按照順序執行
管程鎖定規則: 在同一個monitor上,unlock操作時間上先行發生於後面的lock操作
volatile變數規則: 對一個volatile變數的寫操作先於讀操作
執行緒啟動原則: Thread的start()先於該執行緒的任何操作
執行緒終止原則: Thread的所有操作都先於執行緒的終止檢測。可以通過Thread.join()和Thread.isAlive()的返回值檢測執行緒是否已終止
執行緒終斷規則: 執行緒的interrupt()方法先於中斷執行緒檢測到中斷事件的發生,即可以使用interrupted()方法檢測到執行緒是否被中斷了。
物件終結原則: 物件建構函式執行完畢先於finilized()方法
傳遞性: A先於B,B先於C。可以推斷出A先於C

4.java主記憶體和工作記憶體互動的8個原子操作。

1.lock 將主記憶體的變數鎖住。
2.unlock 主記憶體的變數解鎖,其他執行緒可以獲取這個變數
3.read 把主記憶體的變數讀到寫到工作記憶體裡面
4.load 把read讀取到的值存在本地的副本里面
5.usage 把本地變數的副本交給cpu執行
6.assign 把返回的結果複製給本地副本
7.store 把本地副本的值寫到主記憶體
8.write 把主記憶體的值複製給主記憶體的變數
那麼從jvm的層面來說就可以通過read和store這兩個原子操作來保證記憶體可見性。就是讀之前必須先執行read和load操作,寫之後必須先執行store和write。
也就是所有的寫必須happens-before讀。