摘要:緩存行也必須監聽其它緩存使該緩存行無效或者獨享該緩存行的請求,并將該緩存行變成無效。無注意對于和狀態而言總是精確的,他們在和該緩存行的真正狀態是一致的,而狀態可能是非一致的。多線程并發的優勢和缺點
CPU緩存一致性協議MESI
CPU在摩爾定律的指導下以每18個月翻一番的速度在發展,然而內存和硬盤的發展速度遠遠不及CPU。這就造成了高性能能的內存和硬盤價格及其昂貴。然而CPU的高度運算需要高速的數據。為了解決這個問題,CPU廠商在CPU中內置了少量的高速緩存以解決IO速度和CPU運算速度之間的不匹配問題。
在CPU訪問存儲設備時,無論是存取數據抑或存取指令,都趨于聚集在一片連續的區域中,這就被稱為局部性原理。
時間局部性(Temporal Locality):如果一個信息項正在被訪問,那么在近期它很可能還會被再次訪問。
比如循環、遞歸、方法的反復調用等。
空間局部性(Spatial Locality):如果一個存儲器的位置被引用,那么將來他附近的位置也會被引用。
比如順序執行的代碼、連續創建的兩個對象、數組等
程序以及數據被加載到主內存
指令和數據被加載到CPU的高速緩存
CPU執行指令,把結果寫到高速緩存
高速緩存中的數據寫回主內存
MESI協議緩存狀態
緩存行(Cache line):緩存存儲數據的單元。
狀態 | 描述 | 監聽任務 |
---|---|---|
M 修改 (Modified) | 該Cache line有效,數據被修改了,和內存中的數據不一致,數據只存在于本Cache中。 | 緩存行必須時刻監聽所有試圖讀該緩存行相對就主存的操作,這種操作必須在緩存將該緩存行寫回主存并將狀態變成S(共享)狀態之前被延遲執行。 |
E 獨享、互斥 (Exclusive) | 該Cache line有效,數據和內存中的數據一致,數據只存在于本Cache中。 | 緩存行也必須監聽其它緩存讀主存中該緩存行的操作,一旦有這種操作,該緩存行需要變成S(共享)狀態。 |
S 共享 (Shared) | 該Cache line有效,數據和內存中的數據一致,數據存在于很多Cache中。 | 緩存行也必須監聽其它緩存使該緩存行無效或者獨享該緩存行的請求,并將該緩存行變成無效(Invalid)。 |
I 無效 (Invalid) | 該Cache line無效。 | 無 |
注意:
對于M和E狀態而言總是精確的,他們在和該緩存行的真正狀態是一致的,而S狀態可能是非一致的。如果一個緩存將處于S狀態的緩存行作廢了,而另一個緩存實際上可能已經獨享了該緩存行,但是該緩存卻不會將該緩存行升遷為E狀態,這是因為其它緩存不會廣播他們作廢掉該緩存行的通知,同樣由于緩存并沒有保存該緩存行的copy的數量,因此(即使有這種通知)也沒有辦法確定自己是否已經獨享了該緩存行。
從上面的意義看來E狀態是一種投機性的優化:如果一個CPU想修改一個處于S狀態的緩存行,總線事務需要將所有該緩存行的copy變成invalid狀態,而修改E狀態的緩存不需要使用總線事務。
處理器為提高運算速度兒做出違背代碼原有順序的優化。
在單核處理器時代處理器的亂序執行優化不會影響執行結果。在多核處理中,某個核心執行寫入操作時,將某個標志當做寫入完成,進行重排優化,可能會先執行標志指令導致其他核心以為改核心已經執行完成寫入操作。從而拿到錯誤的值。
堆heap
堆是運行時確定的內存,由java GC來維護大小,優點是可以動態的確定大小,缺點是運行時動態確定內存所以速度相對棧小一點。對象存放在堆上。靜態變量跟隨類一起存放在堆上。
棧stack
棧內存的速度相對堆內存更快,僅次于寄存器,缺點是大小必須是編譯期確定的。缺乏一定的靈活性,存放一些基本的數據變量(int double。。。)java內存要求本地變量(Local Variable),調用棧必須存放在線程棧(Thead Stack)中。
本地變量可能存放的是對象的引用。當兩個線程同時引用一個對象時,那么這兩個線程的本地引用存放的是這個對象的私有拷貝。
硬件內存模型如圖
硬件內存模型和java內存模型的對應模型如圖:
java內存抽象模型結構
看圖,本地內存:本地內存是java抽象的概念,涵蓋了緩存,寫緩存區,寄存器,其他硬件和編譯器優化。本地內存儲存了共享變量的副本,從硬件的角度上講主內存就是硬件內存,但是為了獲取更好的速度,java可能會將數據存儲在寄存器或者高速緩存區。如果線程要通信必須要經過主內存,流程是先在主內存中獲取共享變量,存儲在本地內存中經由進程計算,然后刷新至主內存,再經由其他線程訪問。
lock和Unlack:作用在主內存上只有在Unlock的情況下內存才可以被其他線程鎖定。
Read:作用在主內存上,把主內存中的變量輸送在工作內存中。
Load:作用工作內存中,把主內存中的值放入到工作內存副本中。
use:作用于工作內存,把數據給執行引擎。每當執行器需要使用到變量時或者執行字節碼指令時會執行這個操作。
assign:賦值,在執行賦值操作時執行,將執行引擎中的值賦值給工作內存。
store:存儲,把工作內存中的值傳遞到主內存中。
write:寫入,將工作內存中的值寫入到主內存中。
下面介紹一下規則,規則是用來限制每一步是如何操作的。
不允許read和load、store和write單一出現,因為他們是一個連貫的操作。而且必須是按順序執行的。load必須是read之后,write必須是store之后,但是不一定是連續操作,在他們之間可以插入其他的指令。
不允許線程丟棄assign操作,也就是說執行完了之后必須放入工作內存中。
不允許線程不經過Assign操作直接把數據給主內存。
一個新的變量只能在主內存中誕生。
一個變量只允許一個線程對其lack操作,但是可以被一個線程lack多次,lack多次之后只有執行相同次數的unlack才能被解鎖。
如果一個變量執行了lack操作之后將會清楚工作內存中該變量的值。執行引擎在使用變量時需要重新執行read-load-use等操作。
如果沒有執行一個lack操作的變量不能執行unlack操作。或者被其他線程執行了lack操作的線程也不能被改線程執行unlack。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/73328.html
摘要:系統級線程核心級線程由操作系統內核進行管理。值得注意的是多線程的存在,不是提高程序的執行速度。實現多線程上面說了一大堆基礎,理解完的話。虛擬機的啟動是單線程的還是多線程的是多線程的。 前言 之前花了一個星期回顧了Java集合: Collection總覽 List集合就這么簡單【源碼剖析】 Map集合、散列表、紅黑樹介紹 HashMap就是這么簡單【源碼剖析】 LinkedHashMa...
摘要:本文重點掌握異步編程的相關概念了解期物的概念意義和使用方法了解中的阻塞型函數釋放的特點。一異步編程相關概念阻塞程序未得到所需計算資源時被掛起的狀態。 導語:本文章記錄了本人在學習Python基礎之控制流程篇的重點知識及個人心得,打算入門Python的朋友們可以來一起學習并交流。 本文重點: 1、掌握異步編程的相關概念;2、了解期物future的概念、意義和使用方法;3、了解Python...
摘要:程序執行時,至少會有一個線程在運行,這個運行的線程被稱為主線程。程序的終止是指除守護線程以外的線程全部終止。多線程程序由多個線程組成的程序稱為多線程程序。線程休眠期間可以被中斷,中斷將會拋出異常。 線程 我們在閱讀程序時,表面看來是在跟蹤程序的處理流程,實際上跟蹤的是線程的執行。 單線程程序 在單線程程序中,在某個時間點執行的處理只有一個。 Java 程序執行時,至少會有一個線程在運行...
閱讀 575·2023-04-26 02:58
閱讀 2315·2021-09-27 14:01
閱讀 3622·2021-09-22 15:57
閱讀 1183·2019-08-30 15:56
閱讀 1053·2019-08-30 15:53
閱讀 801·2019-08-30 15:52
閱讀 656·2019-08-26 14:01
閱讀 2174·2019-08-26 13:41