併發編程——處理器進行原子操作的基本原理

原子本意是“不能被進一步分割的最小粒子”,而原子操作意爲“不可被中斷的一個或一系列操作”。在開發過程中,對共享數據進行操作,爲了數據的準確無誤,我們需要保證操作的原子性。本篇文章讓我們瞭解一下處理器是如何實現原子操作的。(本文所說的處理器爲Intel系列處理器)

處理器如何實現原子操作

首先處理器會自動保證基本內存操作的原子性。處理器保證從系統內存中讀取或者寫 入一個字節是原子的,意思是當一個處理器讀取一個字節時,其他處理器不能訪問這個字節 的內存地址。最新的處理器能自動保證單處理器對同一個緩存行裏進行16/32/64位的操作是原子的,但是複雜的內存操作處理器是不能自動保證其原子性的,比如跨總線寬度、跨多個緩存行和跨頁表的訪問。但是,處理器提供總線鎖定緩存鎖定兩個機制來保證複雜內存操作的原子性。

1 使用總線鎖保證原子性

舉一個例子

CUP1,CPU2,CPU3從內存中讀取i,各自加1後寫入內存中。上述操作是在各自CPU內進行的操作,沒有保證操作的原子性。如果想要保證操作的原子性,就意爲着其中一個CPU在進行操作時,其它的CPU不能進行操作,需要等待。

處理器的總線鎖就是來解決這個問題的。什麼是總線鎖呢?

既然說到了總線鎖,就得先了解一下什麼是總線?

如果說主板是一座城市,那麼總線就像是城市裏的公共汽車,能按照固定行車路線,傳輸來回不停運作的比特。這些線路在同一時間內都僅能負責傳輸一個比特。標紅的這句話很重要,要考的,要考的,要考的。它就是實現原子操作的關鍵元素之一。

百度詞條說的還是很抽象。一句話:總線就是連接各個部件的信息傳輸線,是各個部件共享的傳輸介質,同一時間只負責傳輸一個比特。

總線說完了後,來說說總線鎖。

總線鎖就是使用處理器提供的一個 LOCK#信號,當其中一個處理器在總線上輸出此信號時,其它處理器的請求將被阻塞住,那麼該處理器可以獨佔共享內存。

說到這裏,大家也明白了總線鎖定。但總線鎖定的開銷太大,因爲總線鎖定期間,其它處理器不能操作其它內存地址的數據。所以,下面會說到使用緩存鎖來保證原子性。

 

2 使用緩存鎖保證原子性

事實上保證操作的原子性,就是保障數據在內存中的變化。在同一時刻,我們只需要保證對某個內存地址的操作是原子性即可。

上面說到了總線鎖定的開銷比較大,所以,目前處理器在某些場合下使用緩存鎖定代替總線鎖定來進行優化。

這裏所說的緩存是指計算機CPU的高速緩存(L1,L2,L3)。在處理器準備進行處理的時候,一般會將要處理的數據預加載到高速緩存中,頻繁使用的內存也會在高速緩存中。處理器處理數據會先進入高速緩存中查找,沒有找到再去內存中。高速緩存的命中率很高,基本不需要到內存中查找。

所謂“緩存鎖定”是指內存區域如果被緩存在處理器的緩存行中,並且在Lock操作期間被鎖定,那麼當它執行鎖操作回寫到內存時,處理器不會在總線上聲言LOCK#信號(總線鎖定信號),而是修改內部的內存地址,並允許它的緩存一致性機制來保證操作的原子性,因爲緩存一致性機制會阻止同時修改由兩個以上處理器緩存的內存區域數據,當其他處理器回寫已被鎖定的緩存行的數據時,會使緩存行無效。

3 緩存鎖定不能使用的特殊情況

第一種情況是:當操作的數據不能被緩存在處理器內部,或操作的數據跨多個緩存行 時,則處理器會調用總線鎖定。

第二種情況是:有些處理器不支持緩存鎖定。

 

本文內容參考資料:《併發編程的藝術》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章