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