最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

內存屏障由來及實現思路

 更新時間:2022年01月30日 12:13:44   作者:硬核子牙  
這篇文章主要為大家詳細介紹了內存屏障由來及實現思路的詳細講解,讓大家徹底的理解內存屏障,有需要的朋友可以借鑒參考下,希望能夠有所幫助

很多人知道內存屏障這個東西應該是在學習volatile時看到的,但是對內存屏障依然存在很多疑惑:為什么要加內存屏障?內存屏障能解決什么問題?為什么能解決這些問題?

最近在研究volatile的過程中發(fā)現內存屏障這東西如果不搞明白,Java中的volatile就別想學透,所以花了較長時間來研究這塊。看了很多資料,寫了很多代碼測試,這篇文章就來總結下我目前認知中的內存屏障。

01 CPU緩存

如果你不了解講內存屏障為什么要講CPU緩存,接著往后看。

學過《計算機組成原理》的同學應該都聽過一個詞:時鐘周期。什么是時鐘周期呢?通俗點來講就是CPU完成一個基本動作需要的時間周期。對硬件有點認識的同學都知道看CPU好不好一定要看的一個參數:多少多少GHZ。這個GHZ跟時鐘周期之間是存在一定的換算關系的,感興趣的同學可以去自行研究。說明一下:不了解這層換算關系不影響你看后面的內容,只要你對時鐘周期有一個基本認知就可以了。

在很早以前,CPU里面是沒有緩存這塊區(qū)域的,就是CPU直接讀寫內存。那后面為什么在CPU中增加了緩存呢?因為CPU的運行效率與讀寫內存的效率存在著巨大的鴻溝,在讀寫內存過程中帶來的等待浪費了很大的CPU算力?,F在最新的內存是DDR4規(guī)格,但是向內存中寫入數據,據權威資料,需要107個CPU時鐘周期,即CPU的運行效率是寫內存的107倍。如果CPU只執(zhí)行寫操作需要一個時鐘周期,那CPU等待這個寫完成需要等待106個時鐘周期,是不是很浪費CPU算力?那如何解決呢?就跟我們工作中發(fā)現MySQL出現讀寫瓶頸如何解決是一樣的思維:加緩存。

拿我們今天主流的CPU架構來說,現在的CPU主要采用三層緩存:

  • L1、L2緩存成為本地核心內緩存,即一個核一個。如果你的機器是4核,那就是有4個L1+4個L2

  • L3緩存是所有核共享的。即不管你的CPU是幾核,這個CPU中只有一個L3

  • L1緩存的大小是64K,即32K指令緩存+32K數據緩存。L2是256K,L3是2M。這不是絕對的,目前Intel CPU基本是這樣的設計

這里還補充一個知識點:緩存行(Cache-line)。緩存行是CPU緩存存儲數據的最小單位,大小為64B。這塊如果展開來講要講很久很久,本篇文章就不展開講了,有興趣的同學可以自行研究。如果你沒有學習過計算機硬件相關知識,可能看不懂。

根據哲學的矛盾相對論:任何問題的解決方案都是一個利與弊共存的矛盾體。加緩存的確有效提升了CPU的執(zhí)行效率,但是CPU緩存間的數據一致性、CPU緩存與內存間的數據一致性就是不得不去思考與解決的問題了。而且還得保證解決這兩層數據一致性的效率要高于不加緩存前浪費的CPU算力,不然這個方案就是一套偽方案:聽起來高大上,不解決問題。

02 緩存的一致性

MESI協議就是為了保證CPU各核的緩存、內存間的數據一致性而生的,沒有了解過的可以百度普及一下,這個比較簡單。這里拓展兩點:

一、CPU運算單元與L1緩存間為什么要增加buffer?CPU實現各個核的緩存與內存間的數據一致性的思路有點像socket的三次握手:CPU0修改了某個數據,需要廣播告訴其他CPU,這時候CPU0進入阻塞狀態(tài)等待其他CPU修改其緩存中的狀態(tài),待其他CPU都修改完狀態(tài)返回應答消息后才進入運行狀態(tài)。雖然這個阻塞的時間很短,但是在CPU的世界里就很長了,為了保證這部分阻塞時間也能得到充分利用,于是加入了buffer。將預讀信息存儲進去,這樣CPU解除阻塞后就可以直接從buffer拿出請求處理。

二、MESI協議的實現思路是:如果CPU0修改了某個數據,需要廣播給其他CPU,緩存中沒有這個數據的CPU丟棄這個廣播消息,緩存中有這個數據的CPU監(jiān)聽到這個廣播后會將相應的緩存行改為invalid狀態(tài),這樣CPU在下次讀取這個數據的時候發(fā)現緩存行失效,就去內存中讀取。這里面童鞋們有沒有發(fā)現一個問題:只要存在數據修改,CPU就需要去內存取數據,那為什么不實現CPU緩存能共享數據呢?這樣CPU在下次讀取的時候去CPU0的緩存行去讀取就可以啦,而且性能更高?,F在的CPU也的確實現了這個思路,對應的協議就是:AMD的MOESI、Intel的MESIF。感興趣的童鞋自己去研究吧。

03 內存屏障的由來

對于CPU的寫,目前主流策略有兩種:

1、write back:即CPU向內存寫數據時,先把真實數據放入store buffer中,待到某個合適的時間點,CPU才會將store buffer中的數據刷到內存中,而且這兩個操作是異步的。這在多線程環(huán)境中,有些情況下是可以接受的,但是有些情況是不可接受的,為了讓程序員有能力根據業(yè)務需要達到同步完成,就設計了內存屏障。關于內存屏障,后面會細講。

2、write through:即CPU向內存寫數據時,同步完成寫store buffer與內存。

當前CPU大多數采用的是write back策略??赡苡型獑柫耍簽槭裁茨??因為大多數情況下,CPU異步完成寫內存產生的部分延遲是可以接受的,而且這個延遲極短。只有在多線程環(huán)境下需要嚴格保證內存可見等極少數特殊情況下才需要保證CPU的寫在外界看來是同步完成的,需要借助CPU提供的內存屏障實現。如果直接采用策略2:write through,那每次寫內存都需要等待數據刷入內存,極大影響了CPU的執(zhí)行效率。

04 內存屏障實現思路

為什么要插入屏障?本質是業(yè)務層面不能接受寫store buffer與刷回內存這兩個異步操作產生的哪怕是極少的延遲,即對內存可見性的要求極高。

內存屏障到底是什么?內存屏障什么都不是,它只是一個抽象概念,就像OOP。如果這樣說你不理解,那你把他理解成一堵墻,這堵墻正面與反面的指令無法被CPU亂序執(zhí)行及這堵墻正面與反面的讀寫操作需有序執(zhí)行。

CPU提供了三個匯編指令串行化運行讀寫指令達到實現保證讀寫有序性的目的:

SFENCE:在該指令前的寫操作必須在該指令后的寫操作前完成

LFENCE:在該指令前的讀操作必須在該指令后的讀操作前完成

MFENCE:在該指令前的讀寫操作必須在該指令后的讀寫操作前完成

何謂串行化?你可以理解成CPU把讀、寫、讀寫請求放入了一個隊列,按照先進先出的順序執(zhí)行下去;何謂讀操作完成,即CPU執(zhí)行一次讀操作,把值讀到了寄存器中;何謂寫操作完成,即CPU執(zhí)行一次寫操作,數據刷到內存中了。

到這里就把內存屏障講清楚了,你悟了嗎?

以上就是內存屏障由來及實現思路的詳細內容,更多關于內存屏障的資料請關注腳本之家其它相關文章!

相關文章

  • SpringBoot?項目中創(chuàng)建線程池

    SpringBoot?項目中創(chuàng)建線程池

    這篇文章主要介紹了SpringBoot?項目中創(chuàng)建線程池,文章基于Spring?Boot項目創(chuàng)建線程池ThreadPoolExecutor,需要的小伙伴可以參考一下
    2022-04-04
  • guava中Multimap、HashMultimap用法小結

    guava中Multimap、HashMultimap用法小結

    這篇文章主要介紹了guava中Multimap、HashMultimap使用,Multimap它可以很簡單的實現一些功能,LinkedHashMultimap實現類與HashMultimap類的實現方法一樣,唯一的區(qū)別是LinkedHashMultimap保存了記錄的插入順序,本文就這些內容講解的非常詳細,需要的朋友參考下吧
    2022-05-05
  • 使用Java反射獲取方法的全路徑名稱的步驟

    使用Java反射獲取方法的全路徑名稱的步驟

    Java反射是一個強大的特性,它允許程序在運行時查詢和修改類的行為,反射可以用于實現很多高級功能,比如動態(tài)代理、依賴注入等,本文將介紹如何使用Java反射來實現這一功能,需要的朋友可以參考下
    2024-07-07
  • Java 泛型 Generic機制實例詳解

    Java 泛型 Generic機制實例詳解

    這篇文章主要為大家介紹了Java 泛型 Generic機制實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-11-11
  • SWT(JFace)體驗之RowLayout布局

    SWT(JFace)體驗之RowLayout布局

    相對于FillLayout來說,RowLayout比較靈活,功能也比較強。用戶可以設置布局中子元素的大小、邊距、換行及間距等屬性。
    2009-06-06
  • MyBatis攔截器實現分頁功能實例

    MyBatis攔截器實現分頁功能實例

    本篇文章主要介紹了MyBatis攔截器實現分頁功能實例,這里整理了詳細的代碼,有需要的小伙伴可以參考下。
    2017-04-04
  • SpringCloud基于Feign實現遠程調用的問題小結

    SpringCloud基于Feign實現遠程調用的問題小結

    這篇文章主要介紹了SpringCloud基于Feign遠程調用,通過使用 Feign 的方式,我們可以更加優(yōu)雅地進行多參數的遠程調用,避免了手動拼接URL或構建復雜的請求體,需要的朋友可以參考下
    2024-02-02
  • 探索HttpClient中的close方法及其對連接的影響

    探索HttpClient中的close方法及其對連接的影響

    這篇文章主要為大家介紹了HttpClient中的close方法及其對連接的影響探索分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-10-10
  • SpringBoot根據參數動態(tài)調用接口實現類方法

    SpringBoot根據參數動態(tài)調用接口實現類方法

    在?Spring?Boot?開發(fā)中,我們經常會遇到根據不同參數調用接口不同實現類方法的需求,本文將詳細介紹如何實現這一功能,有需要的小伙伴可以參考下
    2025-02-02
  • Java利用正則取標簽之間的數據

    Java利用正則取標簽之間的數據

    這篇文章主要介紹了Java利用正則取標簽之間的數據,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08

最新評論

彭山县| 鄂伦春自治旗| 革吉县| 江津市| 宣恩县| 青阳县| 景谷| 苍梧县| 和林格尔县| 沁源县| 疏附县| 澎湖县| 乌兰浩特市| 铜山县| 杨浦区| 辽中县| 天柱县| 通江县| 拜城县| 湘阴县| 宜春市| 永仁县| 称多县| 丰都县| 沙河市| 阿城市| 客服| 江津市| 西和县| 如皋市| 石河子市| 武夷山市| 光泽县| 日喀则市| 绥化市| 和政县| 雅江县| 北辰区| 高碑店市| 乃东县| 卓尼县|