解決競態問題之原子操作

2021-10-24 06:37:03 字數 2667 閱讀 6069

原子操作簡介:

原子操作就是:指不能再進一步分割的操作

一般原子操作用於:<整形操作>或者<位操作>。

假如現在要對無符號整形變數 a 賦值,值為3,對於 c 語言來講很簡單,直接就是:a = 3

但是 c 語言要先編譯為成彙編指令,arm 架構不支援直接對暫存器進行讀寫操作,比如 要借助暫存器 r0、r1 等來完成賦值操作。假設變數 a 的位址為 0x3000000,「a=3」這一行 c 語言可能會被編譯為如下所示的彙編**:

ldr r0, =0x30000000 /* 變數 a 位址 /

ldr r1, = 3 / 要寫入的值 /

str r1, [r0] / 將 3 寫入到 a 變數中 */

假設現在執行緒 a要向 a 變數寫入 10 這個值,而執行緒 b也要向 a 變數寫入 20 這個值,我們理想中的執行順序:

確實可以實現執行緒 a將 a 變數設定為 10,執行緒 b將 a 變數設定為 20。但是實際上的執行流程可能如圖 下 所示:

執行緒 a最終將變數 a 設定為了 20,而並不是要求的 10!執行緒b沒有問題。這就是乙個最簡單的設定變數值的併發與競爭的例子,要解決這個問題就要保證**a=10中的三行彙編指令作為乙個整體執行,也就是作為乙個原子存在。linux核心提供了一組原子操作 api函式來完成此功能,linux 核心提供了兩組原子操作 api 函式,一組是對整形變數進行操作的,一組是對位進行操作的,我們接下來看一下這些 api 函式。

1、原子整形操作 api 函式:

linux 核心定義了叫做atomic_t的結構體來完成整形資料的原子操作,在使用中用原子變數來代替整形變數,此結構體定義在include/linux/types.h檔案中,定義如下:

typedef struct atomic_t;
如果要使用原子操作 api 函式,首先要先定義乙個atomic_t型別的變數,如下所示:

atomic_t a; //定義 a
也可以在定義原子變數的時候通過巨集atomic_init()向原子變數賦初值給原子變數賦初值,如下所示:

atomic_t b = atomic_init(0)

; //定義原子變數 b 並賦初值為 0

原子變數有了,接下來就是對原子變數進行操作,比如讀、寫、增加、減少等等,linux 內

核提供了大量的原子操作 api 函式,如下所示:

注意:

如果使用64 位的 soc的話,就要用到64位的原子變數,linux 核心也定義了 64 位原子 結構體,如下所示:

typedef struct  atomic64_t;
相應的也提供了 64 位原子變數的操作 api 函式,這裡就不講了,和表中的 api

函式有用法一樣,只是將「atomic_」字首換為「atomic64_」,將int換為long long

atomic_t v =

atomic_init(0

);/* 定義並初始化原子變零 v=0 */

atomic_set(10

);/* 設定 v=10 */

atomic_read

(&v)

;/* 讀取 v 的值,肯定是 10 */

atomic_inc

(&v)

;/* v 的值加 1,v=11 */

2、原子位操作 api 函式:

位操作也是很常用的操作,linux 核心也提供了一系列的原子位操作 api 函式,只不過原 子位操作不像原子整形變數那樣有個atomic_t的資料結構,原子位操作是直接對記憶體進行操作, api 函式如表 下 所示:

解決競態問題之訊號量

1 訊號量簡介 訊號量是同步的一種方式,linux 核心也提供了訊號量機制,訊號量常常用於控制對共享資源的訪問。舉乙個很常見的例子,某個停車場有 100個停車位,這 100 個停車位大家都可以用,對於大家來說這100 個停車位就是共享資源。假設現在這個停車場正常執行,你要把車停到這個這個停車場肯定要...

linux作業系統之競態條件(時序競態)

1 時序競態 前後兩次執行同乙個程式,出現的結果不同。2 pause函式 使用該函式會造成程序主動掛起,並等待訊號喚醒,呼叫該系統呼叫的程序會處於阻塞狀態 主動放棄cpu 函式原型 int pause void 返回值為 1,並設定errno為eintr 使用pause和alarm實現sleep函式...

原子性 競態條件 加鎖機制

首先直接上 下面是一段servlet public long getcount public void service servletrequest req servletresponse resp 上面這個 是為了統計有多個次訪問了servlet。但是該類是執行緒不安全的,因為 count看上去只...