原子操作 普通鎖 讀寫鎖

2022-02-27 01:44:09 字數 1978 閱讀 5619

一:原子操作cas(compare-and-swap)

原子操作分三步:讀取addr的值,和old進行比較,如果相等,則將new賦值給*addr,他能保證這三步一起執行完成,叫原子操作也就是說它不能再分了,當有乙個cpu在訪問這塊內容addr時,其他cpu就不能訪問

)text ·compareandswapuint64(sb),nosplit,$

0-25

movd addr+0

(fp), r3

movd old+8

(fp), r4

movd

new+16

(fp), r5

sync

ldar (r3), r6

cmp r6, r4

bne

7(pc)

stdccc r5, (r3)

bne -4

(pc)

isync

movd $

1, r3

(fp)

ret(fp)

ret二:普通鎖

加鎖(mutex.lock)

1:原子操作加鎖:原子操作判斷是否已經被加鎖,如果沒有加鎖,原子操作加鎖,直接返回,很快嗎!

2:執行旋轉鎖:已經被加鎖,判斷是否可以執行旋轉鎖,執行旋轉鎖,原子判斷是否可以加鎖,若可以,加鎖返回

3:當前g休眠等待被喚醒:在執行旋轉鎖期間,鎖還是沒釋放,那就只能讓當前協程休眠,等待被喚醒,當鎖被釋放後,當前g被喚醒繼續執行

釋放鎖(mutex.unlock)

1:將加鎖狀態去掉,判斷是否有等待的協程,如沒有直接返回

2:若有等待協程,將狀態設定成喚醒狀態

3:喚醒乙個等待協程

三:讀寫鎖

讀寫鎖基於普通鎖實現

加寫鎖(rwmutex.lock)

1:加普通鎖

2:改讀鎖的數量readercount -= 1 << 30

3:如果有正在讀的鎖,等待直到讀鎖完成,讀寫不能同時進行

釋放寫鎖(rwmutex.unlock)

1:改讀鎖的數量readercount += 1 << 30,加鎖的時候減了這麼多,釋放鎖的時候加回來

2:如果readercount>=  1 << 30,拋異常,釋放沒有加鎖的鎖

3:喚醒所有正在等待讀的協程

4:釋放普通鎖

加讀鎖(rwmutex.rlock)

1:原子操作讀鎖數量加1,readercount+=1

2:如果redercount<0,說明有寫功能正在執行,協程進入睡眠狀態,等待寫完之後被喚醒

3:如果沒有正在執行的寫鎖,就完事了,整個加鎖操作就只執行了乙個原子操作,還是很快的

釋放讀鎖(rwmutex.runlock)

1:原子操作讀鎖數量減1

2:如果讀鎖數量==-1,或==-1 << 30,說明釋放了乙個沒有加讀鎖的鎖,或者釋放了乙個正在寫的鎖,直接報錯

3:如果有正在等待的寫鎖,喚醒它,否則整個釋放讀鎖也就執行了乙個原子操作

所以說,鎖是基於原子操作的,原子操作保證了資料的一致性,讀寫鎖基於普通鎖來實現,對於乙個寫少讀多的程式來說,讀寫鎖會比普通鎖快很多

加鎖原理

1:先是cas的方式嘗試獲取鎖,如果獲取到了,就鎖住,並繼續執行被鎖住的**,然後在釋放鎖

2:cas沒有拿到鎖,就只能等待了,比如有10個協程(g)在等這個待鎖,go並不是一把鎖建立乙個佇列,而是預設建立251個佇列,通過hash的方式將g加入佇列,確保等待同一把鎖的g在同乙個佇列,然後將當前g執行上下文資訊儲存到g.sched,下次就可以繼續從這裡執行,這樣這個等待的g就這樣被扔到佇列中了,而不是將這個g狀態改成等待狀態等待被喚醒,g去睡覺了,p還得繼續執行,於是會找乙個p,繼續執行

解鎖原理

1:通過鎖定位到對應的佇列,所有等待這把鎖的g都在這個佇列中,查詢是否有等待的g,沒有就返回

2:有就將g狀態改成可執行,並加入到執行佇列,等待被排程

關於g排程請看我的這篇文章:go併發排程原理學習

Linux原子操作,讀寫鎖機制

若干組合語言指令具有 讀 修改 寫 型別 也就是說,他們訪問儲存單元兩次,第一次讀原值,第二次寫新值。假定執行在兩個cpu上的兩個核心控制路徑試圖通過執行非原子操作來同時 讀 修改 寫 同乙個儲存器單元。首先,兩個cpu都試圖讀同乙個單元,但是儲存器仲裁器 對訪問ram晶元的操作進行序列化的硬體電路...

原子操作和鎖

原子操作 在多程序 執行緒 的作業系統中不能被其它程序 執行緒 打斷的操作就叫原子操作,檔案的原子操作是指操作檔案時的不能被打斷的操作。原子操作是不可分割的,在執行過程中不會被任何其它任務或事件中斷。linux核心提供了一系列函式來實現核心中的原子操作,這些函式又分為兩類,分別針對位和整型變數進行原...

mysql 原子鎖 Go語言檔案鎖操作

我們使用go語言開發一些程式的時候,往往出現多個程序同時操作同一份檔案的情況,這很容易導致檔案中的資料混亂。這時我們就需要採用一些手段來平衡這些衝突,檔案鎖 flock 應運而生,下面我們就來介紹一下。對於 flock,最常見的例子就是 nginx,程序執行起來後就會把當前的 pid 寫入這個檔案,...