linux 使用 乙個變數atomic_t來表示原子變數。
typedef
struct atomic_t;
可以看到裡面是乙個int 型別的變數。
這裡只分析乙個atomic_add函式
static inline void atomic_add(int i, atomic_t *v)
**如下,可以看到linux 是使用的gcc內嵌彙編實現的這個功能。
內嵌彙編的格式為
asmvolatile(「code」
:output list
:input list
:change list
) 具體可以查閱一下另一篇寫gcc內嵌彙編格式的博文。
彙編就能保證不被中斷?就能原子增加?nonono!這是arm提供的特有的機制。
ldrex和strex指令看arm同步指令之ldrex和strex。
首先 「1: ldrex %0, [%3]\n」,
1:這個是個label 用於後面指令執行失敗進行跳轉重新執行。
這個彙編指令的含義通俗講 就是將v->couter 的值載入到result變數中。並且標記這塊記憶體為獨佔狀態。
然後 add %0, %0, %4 意思就是result = result + i;
strex %1, %0, [%3]這段話的意思就是result的結果儲存到v->couter裡面,重點是,如果這塊記憶體已經被標記為獨佔模式,那麼strex指令會清除獨佔標記,然後將tmp的值變為0.但是如果記憶體沒有被標記為獨佔,或者其他執行緒已經使用strex指令清除獨佔,tmp的值變為1,並且strex指令執行失敗,也就是原子操作失敗。
這也就是為什麼原子操作在 strex和ldrex指令中為什麼能實現同步,也就是read-modify-write機制,多個執行緒同時執行的時候,read和modify都沒問題,但write只能由乙個執行緒執行,其它執行緒不管有沒有read modify都無效。
」 teq %1, #0\n」
」 bne 1b」
這兩句的意思是如果strex指令成功也就是tmp為0,則可忽略,如果strex指令失敗,則tmp變為1,說明其它執行緒已經清除了獨佔了標記了。所以要跳轉到第一句彙編1:這裡再次執行。
核心同步機制
1.通過鎖機制來實現同步,有兩種不同的鎖,一種是鎖被持有時選擇忙等,一種是選擇睡眠等待。2.如何避免死鎖 a.按順序加鎖 b.不要重複加鎖 3.自旋鎖 spin lock 忙等鎖,樂觀 適合持有時間非常短,這是因為要考慮程序上下文切換的開銷。4.訊號量 檢視獲取乙個鎖時候,如果不可用則進入睡眠佇列 ...
linux核心同步機制之自旋鎖
定義 最多只能被乙個可執行執行緒持有。如果乙個執行執行緒試圖獲得乙個被爭用的自旋鎖,那麼該執行緒就會一直進行忙迴圈 旋轉 等待鎖重新可用。自旋鎖有 加鎖 和 解鎖 兩種狀態。加鎖 一直在尋求 解鎖 解鎖 馬上會尋求 加鎖 並原地打轉,所以加鎖位置的 進入臨界區執行,直到解鎖。注意 1.占用臨界區的時...
Linux的原子操作與同步機制
b linux的原子操作與同步機制 b b 併發問題 b 例如c語言語句 count 在未經編譯器優化時生成的彙編 為多條機器指令來實現的。b 例子 b 假設count變數初始值為0。程序1執行完 mov eax,count 後,暫存器eax內儲存了count的值0。此時,程序2被排程執行,搶占了程...