解決可見性使用快取一致性。
防止指令重排序使用記憶體屏障,保證有序性。
有volatile變數修飾的共享變數,編譯時會有lock字首。
·lock字首指令會引起處理器快取回寫到記憶體。(匯流排鎖、快取鎖)
·乙個處理器的快取回寫到記憶體會導致其他處理器的快取無效。(mesi、嗅探)
處理器上有一套完整的協議,來保證 cache 的一致性,比較經典的應該就是mesi 協議了,它的方法是在 cpu 快取中儲存乙個標記位,這個標記為有四種
狀態ø m(modified) 修改快取,當前 cpu 快取已經被修改,表示已經和記憶體中的 資料不一致了
ø i(invalid) 失效快取,說明 cpu 的快取已經不能使用了
ø e(exclusive) 獨佔快取,當前cpu的快取和記憶體中資料保持一直,而且其他 處理器沒有快取該資料
ø s(shared) 共享快取,資料和記憶體中資料一致,並且該資料存在多個 cpu快取中
每個 core 的 cache 控制器不僅知道自己的讀寫操作,也監聽其它 cache 的讀 寫操作,嗅探(snooping)"協議
cpu 的讀取會遵循幾個原則:
如果快取的狀態是 i,那麼就從記憶體中讀取,否則直接從快取讀取
如果快取處於 m 或者 e 的 cpu 嗅探到其他 cpu 有讀的操作,就把自己的緩 存寫入到記憶體,並把自己的狀態設定為 s
做技術人的指路明燈,做職場生涯的精神導師
只有快取狀態是m或e的時候,cpu才可以修改快取中的資料,修改後,緩 存狀態變為 mc
對於宣告了volatile的變數進行寫操作,jvm就會向處理器傳送一條lock字首的指令,把這個變數所在的快取行的數 據寫回到系統記憶體,再根據我們前面提到過的mesi的快取一致性協議,來保證多cpu下的各個快取記憶體中的資料的 一致性。
在多核心多執行緒下的指令重排序會影響可見性問題。
使用記憶體屏障解決
前提是編譯器的優化亂序和cpu的執行亂序。
cpu層面的記憶體屏障
寫屏障(store barrier)
、讀屏障
(load barrier)
和全屏障
(full barrier)
,主要的作用是 ø
防止指令之間的重排序 ø
保證資料的可見性
編譯器層面的
loadload barriers
storestore barriers
loadstore barries
storeload barries
追加64位元組提高併發程式設計的效率。
併發程式設計 volatile
併發程式設計中的三個概念 原子性即乙個操作或者多個操作 要麼全部執行並且執行的過程不會被任何因素打斷,要麼就都不執行 可見性指當多個執行緒訪問同乙個變數時,乙個執行緒修改了這個變數的值,其他執行緒能夠立即看得到修改的值 有序性即程式執行的順序按照 的先後順序執行 jvm在真正執行這段 的時候會保證語...
併發程式設計(3)volatile
原子性,可見性,有序性。只要有乙個不能保證,就有可能導致程式的執行錯誤 synchronized就能保障原子性,可見性,有序性,1.因為synchronized能保障任意乙個時刻只有乙個執行緒執行該 塊,自然就不存在原子性的問題 2.在釋放鎖之前會將變數的修改重新整理到主存中,因此保證可見性 3.又...
volatile底層詳解
執行緒執行時把資料放到棧中 1 啟動執行緒時,位元組碼執行引擎需要往棧裡面新增資料,而這些操作是需要通過cpu來完成的,2 位元組碼執行引擎會把位元組碼交給解釋執行器或者jit優化 兩種方式 翻譯成彙編指令,彙編指令通過硬體翻譯成二進位制,也就是cpu能執行的二進位制語言 位元組碼翻譯成彙編指令較慢...