.課程網(wǎng)站
CPU多級緩存
????左圖為最簡單的高速緩存的配置厕怜,數(shù)據(jù)的讀取和存儲都經(jīng)過高速緩存甚疟,CPU核心與高速緩存有一條特殊的快速通道屯远;主存與高速緩存都連在系統(tǒng)總線上(BUS)這條總線還用于其他組件的通信
????在高速緩存出現(xiàn)后不久暖眼,系統(tǒng)變得越來越復雜哩至,高速緩存與主存之間的速度差異被拉大躏嚎,直到加入了另一級緩存,新加入的這級緩存比第一緩存更大菩貌,并且更慢卢佣,而且經(jīng)濟上不合適,所以有了二級緩存箭阶,甚至是三級緩存
1.為什么需要CPU cache?
????CPU的頻率太快了虚茶,快到主存跟不上,這樣在處理器時鐘周期內仇参,CPU常常需要等待主存嘹叫,浪費資源。? 所以cache的出現(xiàn)诈乒,是為了緩解CPU和內存之間速度的不匹配問題(結構:cpu->cache->memory)罩扇。
2.CPU cache 存在的原理?
局部性原理:CPU 訪問存儲器時,無論是存取指令還是存取數(shù)據(jù)怕磨,所訪問的存取單元都趨于聚集在一個較小的連續(xù)區(qū)域中暮蹂。
時間局部性:如果某個數(shù)據(jù)被訪問寞缝,那么在不久的將來他很可能被再次訪問癌压。
空間局部性:如果某個數(shù)據(jù)被訪問仰泻,那么與他相鄰的數(shù)據(jù)很快也可能被訪問。
3.緩存一致性(MESI)
????MESI協(xié)議中cache line數(shù)據(jù)狀態(tài)有4種滩届,引起數(shù)據(jù)狀態(tài)轉換的CPU cache操作也有4種集侯,因此要理解MESI協(xié)議,就要將這16種狀態(tài)轉換的情況討論清楚帜消。
?初始場景:在最初的時候棠枉,所有的CPU中都沒有數(shù)據(jù),其中一個CPU發(fā)生讀操作泡挺,此時發(fā)生RR(數(shù)據(jù)從主內存中讀取到當前CPU的cache)辈讶,狀態(tài)為E(獨占,只有當前CPU有數(shù)據(jù)娄猫,并且和主存一致)贱除。此時,如果有其他CPU也讀取主存數(shù)據(jù)媳溺,則狀態(tài)修改為S(共享月幌,多個CPU之間擁有相同數(shù)據(jù),并且和主存保持一致)悬蔽,如果其中一個CPU發(fā)生數(shù)據(jù)修改扯躺,那么該CPU中數(shù)據(jù)狀態(tài)修改為M(擁有最新數(shù)據(jù),和主存不一致蝎困,但是以當前CPU中的數(shù)據(jù)為準)录语,并通知其他擁有該數(shù)據(jù)的CPU數(shù)據(jù)失效,其他CPU中的cache line狀態(tài)修改為I(失效禾乘,和主存中的數(shù)據(jù)被認為不一致澎埠,數(shù)據(jù)不可用應該重新獲取)
modify
? ? 場景:當前CPU中數(shù)據(jù)狀態(tài)是modify盖袭,表示當前CPU中擁有最新數(shù)據(jù)失暂,雖然主存中的數(shù)據(jù)和當前CPU中的數(shù)據(jù)不一致,但是以當前CPU中的數(shù)據(jù)為準鳄虱;
? ? LR:此時如果發(fā)生local read弟塞,即當前CPU讀數(shù)據(jù),直接從cache中獲取數(shù)據(jù),擁有最新數(shù)據(jù),因此狀態(tài)不變咬崔;
? ??LW:直接修改本地cache數(shù)據(jù)沐飘,修改后也是當前CPU擁有最新數(shù)據(jù)灯荧,因此狀態(tài)不變靶壮;
? ??RR:因為本地內存中有最新數(shù)據(jù)窝撵,因此當前CPU不會發(fā)生RR和RW俺夕,當本地cache控制器監(jiān)聽到總線上有RR發(fā)生的時扩借,必然是其他CPU發(fā)生了讀主存的操作椒惨,此時為了保證一致性, 當前CPU應該將數(shù)據(jù)寫回主存潮罪,而隨后的RR將會使得其他CPU和當前CPU擁有共同的數(shù)據(jù)康谆,因此狀態(tài)修改為S;
? ??RW(將當前CPU緩存中的數(shù)據(jù)寫入到主內存里面):同RR嫉到,當cache控制器監(jiān)聽到總線發(fā)生RW沃暗,當前CPU會將數(shù)據(jù)寫回主存,因為隨后的RW將會導致主存的數(shù)據(jù)修改何恶,因此狀態(tài)修改成I孽锥;
exclusive
????場景:當前CPU中的數(shù)據(jù)狀態(tài)是exclusive,表示當前CPU獨占數(shù)據(jù)(其他CPU沒有數(shù)據(jù))细层,并且和主存的數(shù)據(jù)一致惜辑;
? ? LR:從本地cache中直接獲取數(shù)據(jù),狀態(tài)不變今艺;
? ? LW:修改本地cache中的數(shù)據(jù)韵丑,狀態(tài)修改成M(因為其他CPU中并沒有該數(shù)據(jù),因此不存在共享問題虚缎,不需要通知其他CPU修改cache line的狀態(tài)為I)撵彻;
? ? RR:因為本地cache中有最新數(shù)據(jù),因此當前CPU cache操作不會發(fā)生RR和RW实牡,當cache控制器監(jiān)聽到總線上發(fā)生RR的時候陌僵,必然是其他CPU發(fā)生了讀取主存的操作,而RR操作不會導致數(shù)據(jù)修改创坞,因此兩個CPU中的數(shù)據(jù)和主存中的數(shù)據(jù)一致碗短,此時cache line狀態(tài)修改為S;
? ? RW:同RR题涨,當cache控制器監(jiān)聽到總線發(fā)生RW偎谁,發(fā)生其他CPU將最新數(shù)據(jù)寫回到主存,此時為了保證緩存一致性纲堵,當前CPU的數(shù)據(jù)狀態(tài)修改為I巡雨;
shared
????場景:當前CPU中的數(shù)據(jù)狀態(tài)是shared,表示當前CPU和其他CPU共享數(shù)據(jù)席函,且數(shù)據(jù)在多個CPU之間一致铐望、多個CPU之間的數(shù)據(jù)和主存一致;
? ? LR:直接從cache中讀取數(shù)據(jù),狀態(tài)不變正蛙;
? ? LW:發(fā)生本地寫督弓,并不會將數(shù)據(jù)立即寫回主存,而是在稍后的一個時間再寫回主存乒验,因此為了保證緩存一致性愚隧,當前CPU的cache line狀態(tài)修改為M,并通知其他擁有該數(shù)據(jù)的CPU該數(shù)據(jù)失效徊件,其他CPU將cache line狀態(tài)修改為I奸攻;
? ? RR:狀態(tài)不變,因為多個CPU中的數(shù)據(jù)和主存一致虱痕;
? ? RW:當監(jiān)聽到總線發(fā)生了RW,意味著其他CPU發(fā)生了寫主存操作辐赞,此時本地cache中的數(shù)據(jù)既不是最新數(shù)據(jù)部翘,和主存也不再一致,因此當前CPU的cache line狀態(tài)修改為I响委;
invalid
????場景:當前CPU中的數(shù)據(jù)狀態(tài)是invalid新思,表示當前CPU中是臟數(shù)據(jù),不可用赘风,其他CPU可能有數(shù)據(jù)夹囚、也可能沒有數(shù)據(jù);
? ? LR:因為當前CPU的cache line數(shù)據(jù)不可用邀窃,因此會發(fā)生RR操作荸哟,此時的情形如下。
? ? ? ? A. 如果其他CPU中無數(shù)據(jù)則狀態(tài)修改為E瞬捕;
? ? ? ? B. 如果其他CPU中有數(shù)據(jù)且狀態(tài)為S或E則狀態(tài)修改為S鞍历;
? ? ? ? C. 如果其他CPU中有數(shù)據(jù)且狀態(tài)為M,那么其他CPU首先發(fā)生RW將M狀態(tài)的數(shù)據(jù)寫回主存并修改狀態(tài)為S肪虎,隨后當前CPU讀取主存數(shù)據(jù)劣砍,也將狀態(tài)修改為S;
? ? LW:因為當前CPU的cache line數(shù)據(jù)無效扇救,因此發(fā)生LW會直接操作本地cache刑枝,此時的情形如下。
? ? ? ? A. 如果其他CPU中無數(shù)據(jù)迅腔,則將本地cache line的狀態(tài)修改為M装畅;
? ? ? ? B. 如果其他CPU中有數(shù)據(jù)且狀態(tài)為S或E,則修改本地cache钾挟,通知其他CPU將數(shù)據(jù)修改為I洁灵,當前CPU中的cache line狀態(tài)修改為M;
? ? ? ? C. 如果其他CPU中有數(shù)據(jù)且狀態(tài)為M,則其他CPU首先將數(shù)據(jù)寫回主存徽千,并將狀態(tài)修改為I苫费,當前CPU中的cache line狀態(tài)修改為M;
? ? RR:監(jiān)聽到總線發(fā)生RR操作双抽,表示有其他CPU讀取內存百框,和本地cache無關,狀態(tài)不變牍汹;
? ? RW:監(jiān)聽到總線發(fā)生RW操作铐维,表示有其他CPU寫主存,和本地cache無關慎菲,狀態(tài)不變嫁蛇;
總結: MESI協(xié)議為了保證多個CPU cache中共享數(shù)據(jù)的一致性,定義了cache line的四種狀態(tài)露该,而CPU對cache的4種操作可能會產生不一致狀態(tài)睬棚,因此cache控制器監(jiān)聽到本地操作和遠程操作的時候, 需要對地址一致的cache line狀態(tài)做出一定的修改解幼,從而保證數(shù)據(jù)在多個cache之間流轉的一致性抑党。
Java內存模型
????Java線程之間的通信采用的是共享內存模型,這里提到的共享內存模型指的是Java內存模型(簡稱JMM)撵摆,JMM決定一個線程對共享變量的寫入何時對另一個線程可見底靠。從抽象的角度來看,JMM定義了線程和主存之間的抽象關系:線程之間的共享變量存儲在主存中(main memory)中特铝,每個線程都有一個私有的本地內存(local memory)暑中,本地內存中存儲了該線程以讀/寫共享變量的副本。本地內存是JMM的一個抽象概念苟呐,并不真實存在痒芝。它涵蓋了緩存,寫緩沖區(qū)牵素,寄存器以及其他的硬件和編譯器優(yōu)化严衬。
JVM對Java內存模型的實現(xiàn)
在JVM內部,Java內存模型把內存分成了兩部分:線程棧區(qū)笆呆、堆區(qū)和方法區(qū)请琳,下圖展示了Java內存模型在JVM中的邏輯視圖:?
? ? 基本類型變量和對象的引用,會被存儲到棧區(qū)赠幕。?
? ? 對象的實例存放在堆區(qū)中俄精。
????Static類型的變量以及類本身相關信息都會隨著類本身存儲在方法區(qū)。
????堆中的對象和方法區(qū)的數(shù)據(jù)可以被多線程共享榕堰。如果一個線程獲得一個對象的應用竖慧,它便可訪問這個對象的成員變量嫌套。如果兩個線程同時調用了同一個對象的同一個方法,那么這兩個線程便可同時訪問這個對象的成員變量圾旨,但是對于本地(局部)變量踱讨,每個線程都會拷貝一份到自己的線程棧中,即不存在多線程競爭同一個資源的問題砍的。
? ? 垃圾回收器GC的工作區(qū)域是在堆中痹筛,會不定時去清除引用不可達的對象。
硬件內存架構
????現(xiàn)代計算機一般都有2個以上CPU廓鞠,而且每個CPU還有可能包含多個核心帚稠。因此,如果我們的應用是多線程的話床佳,這些線程可能會在各個CPU核心中并行運行滋早。
????在CPU內部有一組CPU寄存器,也就是CPU的儲存器夕土。CPU操作寄存器的速度要比操作計算機主存快得多馆衔。在主存和CPU寄存器之間還存在CPU緩存,CPU操作CPU緩存的速度快于主存但慢于CPU寄存器怨绣。某些CPU可能有多個緩存層(一級緩存和二級緩存)。計算機的主存也稱作RAM拷获,所有的CPU都能夠訪問主存篮撑,而且主存比上面提到的緩存和寄存器大很多。
????當一個CPU需要訪問主存時匆瓜,會先讀取一部分主存數(shù)據(jù)到CPU緩存中赢笨,進而再讀取CPU緩存到寄存器。當CPU需要寫數(shù)據(jù)到主存時驮吱,同樣會先flush寄存器到CPU緩存茧妒,然后在某個時間節(jié)點緩存數(shù)據(jù)會flush到主存。
計算機指令的執(zhí)行流程
CPU 是由三個組件組成的:存儲器(高速緩存)左冬、運算器桐筏、控制器。計算機指令的執(zhí)行拇砰,都是在 CUP 的三個組件間流轉的梅忌。控制器主要包括程序計數(shù)器和指令寄存器除破。
1. 存儲器緩存數(shù)據(jù)和指令牧氮。
2. 從程序計數(shù)器中取出將要執(zhí)行的指令地址。
3. 總線通過指令地址到存儲器中取出對應操作碼和地址碼瑰枫,并放入指令寄存器中踱葛。
4. 將指令發(fā)送到指令譯碼器中。
5. 程序計數(shù)器+1,指向下一個要執(zhí)行的指令地址尸诽。
6. 譯碼器對指令進行譯碼甥材。
7. 譯碼器完成譯碼后,向運算器發(fā)送控制信號逊谋。
8. 運算器接收到控制信號后擂达,執(zhí)行指令。