高併發第二彈:併發概念及內存模型(JMM)html
感謝 :java
1.概念程序員
併發:同時擁有兩個或者多個線程,若是程序在單核處理器上運行,多個線程將交替地還如或者換出內存,這些線程是同時」存在」的,每隔線程都處於執行過程當中的某個狀態,若是運行在多核處理器上,此時,程序中的每一個線程都將分配到一個處理器核上,所以能夠同時運行。緩存
高併發:High Concurrency 是互聯網分佈式系統架構設計中必須考慮的因素之一,它一般是指,經過設計保證系統可以同時並行處理不少請求。安全
2. 多級緩存架構
CPU的頻率太快了,快到主存跟不上,這樣在處理器時鐘週期內,CPU經常須要等待主存,浪費資源,因此cache的出現,是爲了緩解CPU和內存之間速度的不匹配問題。
CPU多級緩存配置(演變): 併發
局部性原理:
(1) 時間局部性:若是某個數據被訪問,那麼在不久的未來它極可能被再次訪問。
(2) 空間局部性:若是某個數據被訪問,那麼與他相鄰的數據很快也可能被訪問。分佈式
請注意,這只是示意圖,真正的數據流並不須要流經上級緩存高併發
3.緩存一致性(MESI Modify|Exclusive|Share|Invalid)性能
若是尚未概念,建議看一下 :[每一個程序員都應該瞭解的 CPU 高速緩存]https://www.oschina.net/translate/what-every-programmer-should-know-about-cpu-cache-part2?cmp
1.1 cpu緩存一致性協議MESI >> 更詳細:cpu緩存一致性
MESI 是指4中狀態的首字母。每一個Cache line有4個狀態,可用2個bit表示,它們分別是:
緩存行(Cache line):緩存存儲數據的單元。
狀態 | 描述 | 監放任務 |
---|---|---|
M 修改 (Modified) | 該Cache line有效,數據被修改了,和內存中的數據不一致,數據只存在於本Cache中。 | 緩存行必須時刻監聽全部試圖讀該緩存行相對就主存的操做,這種操做必須在緩存將該緩存行寫回主存並將狀態變成S(共享)狀態以前被延遲執行。 |
E 獨享、互斥 (Exclusive) | 該Cache line有效,數據和內存中的數據一致,數據只存在於本Cache中。 | 緩存行也必須監聽其它緩存讀主存中該緩存行的操做,一旦有這種操做,該緩存行須要變成S(共享)狀態。 |
S 共享 (Shared) | 該Cache line有效,數據和內存中的數據一致,數據存在於不少Cache中。 | 緩存行也必須監聽其它緩存使該緩存行無效或者獨享該緩存行的請求,並將該緩存行變成無效(Invalid)。 |
I 無效 (Invalid) | 該Cache line無效。 | 無 |
理解該圖的前置說明:
1.觸發事件
觸發事件 | 描述 |
---|---|
本地讀取(Local read) | 本地cache讀取本地cache數據 |
本地寫入(Local write) | 本地cache寫入本地cache數據 |
遠端讀取(Remote read) | 其餘cache讀取本地cache數據 |
遠端寫入(Remote write) | 其餘cache寫入本地cache數據 |
2.cache分類:
前提:全部的cache共同緩存了主內存中的某一條數據。
本地cache:指當前cpu的cache。
觸發cache:觸發讀寫事件的cache。
其餘cache:指既除了以上兩種以外的cache。
注意:本地的事件觸發 本地cache和觸發cache爲相同。
下圖示意了,當一個cache line的調整的狀態的時候,另一個cache line 須要調整的狀態。
M | E | S | I | |
---|---|---|---|---|
M | × | × | × | √ |
E | × | × | × | √ |
S | × | × | √ | √ |
I | √ | √ | √ | √ |
舉個栗子來講:
假設cache 1 中有一個變量x = 0的cache line 處於S狀態(共享)。
那麼其餘擁有x變量的cache 二、cache 3等x的cache line調整爲S狀態(共享)或者調整爲 I 狀態(無效)。
更詳細的 我建議去我剛剛分享的那個師兄去看,更詳細
四種操做
void
executedOnCpu0() {
value =
10
;
finished =
true
;
}
void
executedOnCpu1() {
while
(!finished);
assert
value ==
10
;
}
|
試想一下開始執行時,CPU 0保存着finished
在Exclusive狀態,而value
並無保存在它的緩存中。(例如,Invalid)。在這種狀況下,value
會比finished
更遲地拋棄存儲緩存。徹底有可能CPU 1讀取finished
的值爲true
,而value
的值不等於10
。
這種在可識別的行爲中發生的變化稱爲重排序(reordings)。注意,這不意味着你的指令的位置被惡意(或者好意)地更改。
它只是意味着其餘的CPU會讀到跟程序中寫入的順序不同的結果。
Java內存模型抽象結構:每一個線程都有一個私有的本地內存,本地內存他是java內存模型的一個抽象的概念。它並非真實存在的,它涵蓋了緩存、寫緩衝區、寄存器以及其餘的硬件和編譯器的優化。本地內存中它存儲了該線程以讀或寫共享變量拷貝的一個副本。從更低的層次來講,主內存就是硬件的內存,是爲了獲取更高的運行速度,虛擬機及硬件系統可能會讓工做內存優先存儲於寄存器和高速緩存中,java內存模型中的線程的工做內存是CPU的寄存器和高速緩存的一個抽象的描述。而JVM的靜態內存存儲模型它只是對內存的一種物理劃分而已。它只侷限在內存,並且只侷限在JVM的內存。 Write One,Run Everywhere!
風險:
優點: