色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

聊聊原子變量、鎖、內存屏障那點事(1)

Linux閱碼場 ? 來源:未知 ? 作者:李倩 ? 2018-08-30 08:20 ? 次閱讀

突然想聊聊這個話題,是因為知乎上的一個問題多次出現在了我的Timeline里:請問,多個線程可以讀一個變量,只有一個線程可以對這個變量進行寫,到底要不要加鎖?可惜的是很多高票答案語焉不詳,甚至有所錯漏。所以我想在這篇文章里斗膽聊聊這個水挺深的問題。受限于個人水平,文章若有錯漏,還望讀者不吝賜教。

首先約定,由于CPU的架構和設計浩如煙海,本文站在工程師的角度,只談IA32/AMD64(x86-64)架構,不討論其他架構的細節和差異。并且文章中主要引用Intel的文檔予以佐證,不關注AMD在實現細節上的差異。

眾所周知,當一個執行中的程序的數據被多個執行流并發訪問的時候,就會涉及到同步(Synchronization)的問題。同步的目的是保證不同執行流對共享數據并發操作的一致性。早在單核時代,使用鎖或者原子變量就很容易達成這一目的。甚至因為CPU的一些訪存特性,對某些內存對齊數據的讀或寫也具有原子的特性。

比如,在《Intel? 64 and IA-32 Architectures Software Developer’s Manual》的第三卷System Programming Guide的Chapter 8 Multiple-Processor Management里,就給出了這樣的說明:

也就是說,有些內存對齊的數據的訪問在CPU層面就是原子進行的(注意這里說的只是單次的讀或者寫,類似普通變量i的i++操作不止一次內存訪問)。此時,環形隊列(Ring buffer)這種數據結構在某些架構的單核CPU上,只有一個Reader和一個Writer的情況下是不需要額外同步措施的。原因就是read_index和writer_index的寫操作在滿足對齊內存訪問的情況下是原子的,不需要額外的同步措施。注意這里我加粗了單核CPU這個關鍵字,那么到了多核心處理器的今天,該操作就不是原子了嗎?不,依舊是原子的,但是出現了其他的干擾因素迫使可能需要額外的同步措施才能保證原本無鎖代碼的正確運行。

首先是現代編譯器的代碼優化和編譯器指令重排可能會影響到代碼的執行順序。編譯期指令重排是通過調整代碼中的指令順序,在不改變代碼語義的前提下,對變量訪問進行優化。從而盡可能的減少對寄存器的讀取和存儲,并充分復用寄存器。但是編譯器對數據的依賴關系判斷只能在單執行流內,無法判斷其他執行流對競爭數據的依賴關系。就拿無鎖環形隊列來說,如果Writer做的是先放置數據,再更新索引的行為。如果索引先于數據更新,Reader就有可能會因為判斷索引已更新而讀到臟數據。

那禁止編譯器對該類變量的優化,解決了編譯期的重排序就沒事了嗎?不,CPU還有亂序執行(Out-of-Order Execution)的特性。流水線(Pipeline)和亂序執行是現代CPU基本都具有的特性。機器指令在流水線中經歷取指、譯碼、執行、訪存、寫回等操作。為了CPU的執行效率,流水線都是并行處理的,在不影響語義的情況下。處理器次序(Process Ordering,機器指令在CPU實際執行時的順序)和程序次序(Program Ordering,程序代碼的邏輯執行順序)是允許不一致的,即滿足As-if-Serial特性。顯然,這里的不影響語義依舊只能是保證指令間的顯式因果關系,無法保證隱式因果關系。即無法保證語義上不相關但是在程序邏輯上相關的操作序列按序執行。從此單核時代CPU的Self-Consistent特性在多核時代已不存在,多核CPU作為一個整體看,不再滿足Self-Consistent特性。

簡單總結一下,如果不做多余的防護措施,單核時代的無鎖環形隊列在多核CPU中,一個CPU核心上的Writer寫入數據,更新index后。另一個CPU核心上的Reader依靠這個index來判斷數據是否寫入的方式不一定可靠。index有可能先于數據被寫入,從而導致Reader讀到臟數據。

所有的麻煩到這里就結束了嗎?當然不,還有Cache的問題。前文提到的都是順序一致性(Sequential Consistency)的問題,沒有涉及Cache一致性(Cache Coherence)的問題。雖然說一般情況下程序員只需要關注順序一致性即可,但是區分清楚這兩個概念也能更好的解釋內存屏障(Memory Barrier)。

開始提到Cache一致性協議之前,先介紹兩個名詞:

Load/Read CPU讀操作,是指將內存數據加載到寄存器的過程

Store/Write CPU寫操作,是指將寄存器數據寫回主存的過程

現代處理器的緩存一般分為三級,由每一個核心獨享的L1、L2 Cache,以及所有的核心共享L3 Cache組成:

由于Cache的容量很小,一般都是充分的利用局部性原理,按行/塊來和主存進行批量數據交換,以提升數據的訪問效率。以前寫過一篇《淺析x86架構中cache的組織結構》,這里不再贅述。既然各個核心之間有獨立的Cache存儲器,那么這些存儲器之間的數據同步就是個比較復雜的事情。緩存數據的一致性由緩存一致性協議保證。這里比較經典的當屬MESI協議。Intel的處理器使用從MESI中演化出的MESIF協議,而AMD使用MOESI協議。緩存一致性協議的細節超出了本文的討論范圍,有興趣的讀者可以自行研究。

傳統的MESI協議中有兩個行為的執行成本比較大。一個是將某個Cache Line標記為Invalid狀態,另一個是當某Cache Line當前狀態為Invalid時寫入新的數據。所以CPU通過Store Buffer和Invalidate Queue組件來降低這類操作的延時。如圖:

當一個核心在Invalid狀態進行寫入時,首先會給其它CPU核發送Invalid消息,然后把當前寫入的數據寫入到Store Buffer中。然后異步在某個時刻真正的寫入到Cache Line中。當前CPU核如果要讀Cache Line中的數據,需要先掃描Store Buffer之后再讀取Cache Line(Store-Buffer Forwarding)。但是此時其它CPU核是看不到當前核的Store Buffer中的數據的,要等到Store Buffer中的數據被刷到了Cache Line之后才會觸發失效操作。而當一個CPU核收到Invalid消息時,會把消息寫入自身的Invalidate Queue中,隨后異步將其設為Invalid狀態。和Store Buffer不同的是,當前CPU核心使用Cache時并不掃描Invalidate Queue部分,所以可能會有極短時間的臟讀問題。當然這里的Store Buffer和Invalidate Queue的說法是針對一般的SMP架構來說的,不涉及具體架構。事實上除了Store Buffer和Load Buffer,流水線為了實現并行處理,還有Line Fill Buffer/Write Combining Buffer 等組件,參考文獻8-10給出了相關的資料可以進一步閱讀。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 寄存器
    +關注

    關注

    31

    文章

    5336

    瀏覽量

    120232
  • cpu
    cpu
    +關注

    關注

    68

    文章

    10854

    瀏覽量

    211589
  • 編譯器
    +關注

    關注

    1

    文章

    1623

    瀏覽量

    49108

原文標題:淺墨: 聊聊原子變量、鎖、內存屏障那點事(1)

文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    從硬件引申出內存屏障,帶你深入了解Linux內核RCU

    本文從硬件的角度引申出內存屏障,這不是內存屏障的詳盡手冊,但是相關知識對于理解RCU有所幫助。
    的頭像 發表于 09-19 11:39 ?6137次閱讀
    從硬件引申出<b class='flag-5'>內存</b><b class='flag-5'>屏障</b>,帶你深入了解Linux內核RCU

    ARM體系結構之內存序與內存屏障

    本文介紹 Armv8-A 架構的內存序模型,并介紹 arm 的各種內存屏障。本文還會指出一些需要明確內存保序的場景,并指明如何使用內存
    發表于 06-15 18:19 ?1685次閱讀
    ARM體系結構之<b class='flag-5'>內存</b>序與<b class='flag-5'>內存</b><b class='flag-5'>屏障</b>

    詳解Linux內核原子操作

    原子操作(atomic operation),不可分割的操作。其通過原子變量來實現,以保證單個CPU周期內,讀寫該變量,不能被打斷,進而判斷該變量
    發表于 07-04 11:16 ?495次閱讀

    編程中的命名設計那點

    編程中的命名設計那點
    發表于 08-17 09:32

    MCU上的無原子讀操作

    32位變量任何一個字節的時候,剩下的7個字節都可能改變。2、認為在中斷函數建立數據拷貝這個理由同上,無論如何復制,都難以避免讀的瞬間數據被破壞3、建立單字節原子該體系必須支持測試清零指令,而且就算支持
    發表于 03-06 09:39

    CPU和內存那點事兒

    我們之前講過CPU,也說了CPU和內存那點事兒,今天咱就再來說說有關內存,作為一個程序員,你必須要懂的哪那些硬核知識!大白話聊一聊,很重要!先來大白話的跟大家聊一聊,我們這里說的內存
    發表于 07-27 08:02

    導致ARM內存屏障的原因究竟有哪些

    與程序員的代碼邏輯不符,導致一些錯誤的發生,為了保證內存訪問的一致性,也是保證程序的正確性,使用內存屏障來保證內存的訪問順序。ARM采用的是弱一致性
    發表于 05-09 09:32

    學習下ARM內存屏障(memory barrier)指令

    據標記放在普通型內存中。如果需要嚴格的內存訪問順序,即在需要強制排序的情況下,可以通過使用顯式屏障操作來實現。處理器必須始終負責由地址依賴性引起的危險:STR X0, [X2]LDR X1
    發表于 02-07 14:08

    內存屏障是什么

    內存屏障,也稱內存柵欄,內存柵障,屏障指令等, 是一類同步屏障指令,是CPU或編譯器在對
    發表于 11-14 09:43 ?6524次閱讀
    <b class='flag-5'>內存</b><b class='flag-5'>屏障</b>是什么

    聊聊原子變量內存屏障那點(2)

    關于第一點,關于指令重排,這里不考慮架構的話,Load和Store兩種操作會有Load-Store、Store-Load、Load-Load、Store-Store這四種可能的亂序結果。 上文提到的三種屏障則是限制這些不同亂序的機制。
    的頭像 發表于 08-30 08:23 ?3478次閱讀

    可以了解并學習Linux 內核的同步機制

    Linux內核同步機制,挺復雜的一個東西,常用的有自旋,信號量,互斥體,原子操作,順序,RCU,內存屏障等。
    發表于 05-14 14:10 ?700次閱讀

    Linux內核的內存屏障的原理和用法分析

    圈里流傳著一句話“珍愛生命,遠離屏障”,這足以說明內存屏障是一個相當晦澀和難以準確把握的東西。使用過弱的屏障,會導致軟件不穩定。
    的頭像 發表于 09-05 09:13 ?1994次閱讀

    Rust原子類型和內存排序

    原子類型在構建無數據結構,跨線程共享數據,線程間同步等多線程并發編程場景中起到至關重要的作用。本文將從Rust提供的原子類型和原子類型的內存
    的頭像 發表于 10-31 09:21 ?940次閱讀

    一文徹底搞懂內存屏障與volatile

    內存屏障與 volatile 是高并發編程中比較常用的兩個技術,無隊列的時候就會用到這兩項技術。然而這兩項技術涉及比較廣的基礎知識,所以比較難以理解,也比較不容易解釋清楚。關于內存
    的頭像 發表于 11-29 11:43 ?2380次閱讀

    如何實現一個多讀多寫的線程安全的無隊列

    加鎖。那么如何實現一個多讀多寫的線程安全的無隊列呢? 互斥:mutexqueue(太簡單不介紹了) 互斥+條件變量:blockqueue(太簡單不介紹了)
    的頭像 發表于 11-08 15:25 ?1303次閱讀
    如何實現一個多讀多寫的線程安全的無<b class='flag-5'>鎖</b>隊列
    主站蜘蛛池模板: 久久操热在线视频精品| 免费完整版观看| 男同志china免费视频| 色偷偷7777www| 久久精品国产只有精品| 欧美最猛黑人XXXXWWW| 亚洲精品123区| 亚洲免费无码av线观看| 亚洲日韩欧美国产专区| 伊人久久国产精品| 大胆国模一区二区三区伊人 | 亚洲区欧美日韩综合| 99热这里只有精品9| 国产亚洲精品久久久久久禁果TV| 国产人妻人伦精品98| 黑人阴茎插女人图片| 久久婷五月综合色啪首页| 久久久无码精品亚洲欧美| 日韩精品无码免费专区| 午夜快车神马影视| 97夜夜澡人人爽人人模人人喊| 国产精品第3页| 欧美video巨大粗暴18| 杨幂被视频在线观看| 国产99青草全福视在线| 蜜臀AV999无码精品国产| 青青久久国产| 在线综合 亚洲 欧美| 99视频精品在线| 精品精品国产自在现拍| 伸进同桌奶罩里摸她胸作文| 亚洲精品无码午夜福利在线观看| younv 学生国产在线视频| 国产色综合色产在线视频| 欧美国产精品久久久乱码| 一品道门在线视频| 国产亚洲欧洲日韩在线观看| 日韩精品欧美在线视频在线| 99精品国产AV一区二区麻豆| 久久www99re在线播放| 无码国产精品高潮久久9|