原子操作和鎖

2021-05-04 21:58:04 字數 1359 閱讀 1263

原子操作

在多程序(執行緒)的作業系統中不能被其它程序(執行緒)打斷的操作就叫原子操作,檔案的原子操作是指操作檔案時的不能被打斷的操作。原子操作是不可分割的,在執行過程中不會被任何其它任務或事件中斷。

linux核心提供了一系列函式來實現核心中的原子操作,這些函式又分為兩類,分別針對位和整型變數進行原子操作。它們的共同點是在任何情況下操作都是原子的,核心**可以安全地呼叫它們而不被打斷。位和整型變數原子操作都依賴底層cpu的原子操作實現,因此所有這些函式都與cpu的架構密切相關。

在linux中,實現檔案上鎖的函式有lock和fcntl,其中lock用於對檔案施加建議性鎖,而fcntl不僅可以施加建議性鎖,還可以施加強制鎖。同時,fcntl還能對檔案的莫一記錄進行上鎖,也即是記錄鎖。記錄鎖分為讀取鎖(共享鎖)和寫入鎖(排斥鎖)。

自旋鎖是專為防止多處理器併發而引入的一種鎖,它在核心中大量應用於中斷處理等部分(對於單處理器來說,防止中斷處理中的併發可簡單採用關閉中斷的方式,不需要自旋鎖)。

自旋鎖最多只能被乙個核心任務持有,如果乙個核心任務試圖請求乙個已被爭用(已經被持有)的自旋鎖,那麼這個任務就會一直進行忙迴圈——旋轉——等待鎖重新可用。要是鎖未被爭用,請求它的核心任務便能立刻得到它並且繼續進行。自旋鎖可以在任何時刻防止多於乙個的核心任務同時進入臨界區,因此這種鎖可有效地避免多處理器上併發執行的核心任務競爭共享資源。

事實上,自旋鎖的初衷就是:在短期間內進行輕量級的鎖定。乙個被爭用的自旋鎖使得請求它的執行緒在等待鎖重新可用的期間進行自旋(特別浪費處理器時間),所以自旋鎖不應該被持有時間過長。如果需要長時間鎖定的話, 最好使用訊號量。

自旋鎖的基本形式如下:

spin_lock(&mr_lock);

//臨界區

spin_unlock(&mr_lock);

因為自旋鎖在同一時刻只能被最多乙個核心任務持有,所以乙個時刻只有乙個執行緒允許存在於臨界區中。這點很好地滿足了對稱多處理機器需要的鎖定服務。在單處理器上,自旋鎖僅僅當作乙個設定核心搶占的開關。如果核心搶占也不存在,那麼自旋鎖會在編譯時被完全剔除出核心。

簡單的說,自旋鎖在核心中主要用來防止多處理器中併發訪問臨界區,防止核心搶占造成的競爭。另外自旋鎖不允許任務睡眠(持有自旋鎖的任務睡眠會造成自死鎖——因為睡眠有可能造成持有鎖的核心任務被重新排程,而再次申請自己已持有的鎖),它能夠在中斷上下文中使用。

死鎖:假設有乙個或多個核心任務和乙個或多個資源,每個核心都在等待其中的乙個資源,但所有的資源都已經被占用了。這便會發生所有核心任務都在相互等待,但它們永遠不會釋放已經占有的資源,於是任何核心任務都無法獲得所需要的資源,無法繼續執行,這便意味著死鎖發生了。自死瑣是說自己占有了某個資源,然後自己又申請自己已占有的資源,顯然不可能再獲得該資源,因此就自縛手腳了。

鎖 原子操作和golang mutex原始碼詳解

對於某一塊 段,多個執行緒或者協程同時執行會產生一些不符合預期的結果,就需要使用訊號量保護這一段 區,只能由乙個執行緒來占用和執行這段 這相當於是乙個大型的原子操作,由軟體層面來實現 下面是一段結果不符合預期的 段 var count 0 func main wg.add 2 go add wg g...

原子操作 普通鎖 讀寫鎖

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

cuda 原子鎖 多執行緒操作 通用原子操作

在專案中,空間中有200w 的點,需要對映到乙個grid map的600 600的網格中,落入到同乙個格仔的點需要進行一些計算獲得乙個值。對於格仔與格仔之間是並行的,但格仔之中的點需要設計為序列。所以在計算某個格仔中的點時,需要將格仔的值保護起來,只允許乙個執行緒 點 計算並改變。這裡就用到了cud...