Java可見性機制的原理

2021-09-23 06:52:11 字數 1292 閱讀 9590

基本概念

1.可見性

當乙個執行緒修改了共享變數時,另乙個執行緒可以讀取到這個修改後的值。

2.記憶體屏障(memory barriers)

處理器的一組指令,用於實現對記憶體操作的順序限制。

3.緩衝行

cpu告訴快取中可以分配的最小儲存單位,處理器填寫快取行時,會載入整個快取行。

4.lock字首的指令

lock字首的指令在多核處理器下會發生兩件事情:

1)將當預處理器的快取行的資料協會到系統記憶體。

2)這個寫回記憶體的操作會使其他cpu快取了該記憶體的位址的資料無效。

5.快取一致性協議

在多處理器下,為零保證各個處理器的快取是一致的,每個處理器都會通過嗅探在匯流排上傳播的資料來檢查自己快取的值是不是過期了。當處理器發現自己快取行對應的位址被修改,就會將當預處理器的快取行設定為無效狀態。當處理器對這個資料進行讀寫的時候,會重新把資料從記憶體中讀取到處理器快取中。

6.cas

compareandswap 比較並交換

cas操作需要輸入兩個值,乙個舊值(執行cas操作前的值,期望值)和乙個新值,只有當當前值等於舊值時,才可以將當前值設定為新值,否則不設定。這是乙個原子操作,由硬體保證。

7.重排序規則

從根本上來所,jmm 對編譯器和處理器的重排序限制只有一條,只要不改變程式執行的結果(指的是單執行緒或者正確同步的多執行緒環境下),那麼編譯器和處理器怎麼優化都可以。

volatile

從上面的lock字首指令和快取一致性協議可以看出來,這就是volatile的實現原理了。

實際上,valatile變數被寫入時,確實加了乙個lock字首的指定,以此來達到可見性的目的。

final

final域只能被顯示地賦值一次,但是這並不代表final域不能被多次初始化。

比如:final int i ;i在建構函式中被賦值之前,就會被初始化為預設的值:0.通過除錯**可以證明這一點。

為了保證final域的值不會在為初始化的情況下被訪問到,程式設計師只需要保證一點即可:即,在建構函式中,正在被構造的物件(this)沒有「逸出」,那麼不需要任何同步手段,就能保證任意執行緒看到的final域,包括基本型別和引用型別,都是已經被正確地通過建構函式初始化過了的。

乙個會是正在被構造的物件逸出的例子:

public class finaltest }

volatile可見性原理解析

程式執行所需要的資料 讀操作 直接來自於記憶體,而修改變數值 寫操作 實際上有如下三步 1 將主存中的資料載入到快取中 2 對快取中的資料進行修改 3 將修改後的值重新整理到記憶體中 多個執行緒共同操作乙個變數,如下圖 第一步 執行緒1 執行緒2 執行緒3操作的是主存中的同乙個變數,並且分別交由cp...

Java多執行緒可見性(一)

一 記憶體可見性 執行緒對共享變數的修改,可以及時的被其他執行緒看到。那何為共享變數呢?就是在多個執行緒的工作記憶體中存在 如下圖所示 所謂的共享變數就是主記憶體中名為s的變數,程式中所有的變數都會儲存在主記憶體中 其他執行緒也會有自己的工作記憶體,此工作記憶體的作用是為執行緒與主記憶體之間建立橋梁...

繼承的可見性

繼承的可見性 在c 中通過繼承,子類將擁有除父類的 建構函式和析構函式以外的所有的成員.注意這裡的 擁有 和 可見性 是兩個概念.擁有某個成員是指該成員確確實實地存在於該類中,但如果該成員的訪問許可權不允許該成員在繼承的子類中可見 比如private,internal 我們將不能在子類中對他們進行操...