為什麼需要原子性操作?
若是有兩個執行緒同時對同乙個變數++,就會出現問題,如下:
time thread 1 thread 2
0 load eax, x
1 load eax, x
2 add eax, 1
3 add eax, 1
4 store x, eax
5 store x, eax
我們希望的結果是x+2,但結果應該是x+1,原因就是不是原子操作,解決方法有兩個:
一 加鎖,但鎖競爭是高效能伺服器的殺手,所以這裡不能用。
二 gcc原子性操作:
// 原子自增操作//*ptr+value
type __sync_fetch_and_add (type *ptr, type value)
// 原子比較和交換(設定)操作
// if(*ptr==oldval) *ptr=newval,函式返回true,返回失敗,不設定。
type __sync_val_compare_and_swap (type *ptr, type oldval type newval)
bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval)
// 原子賦值操作
type __sync_lock_test_and_set (type *ptr, type value)
使用這些原子性操作,編譯的時候需要加-march=cpu-type
無鎖佇列實現
伺服器開發中,volatile經常用到:
volatile的作用: 作為指令關鍵字,確保本條指令不會因編譯器的優化而省略,且要求每次直接讀值。簡單地說就是防止編譯器對**進行優化
當要求使用volatile 宣告的變數的值的時候,系統總是重新從它所在的記憶體讀取資料,而不是使用儲存在暫存器中的備份。即使它前面的指令剛剛從該處讀取過資料。而且讀取的資料立刻被儲存
C 伺服器開發之筆記三
為什麼需要原子性操作?若是有兩個執行緒同時對同乙個變數 就會出現問題,如下 time thread 1 thread 2 0 load eax,x 1 load eax,x 2 add eax,1 3 add eax,1 4 store x,eax 5 store x,eax 我們希望的結果是x 2...
Linux伺服器開發學習之C
2 字串 向量和陣列 當在程式的某處我們使用了一種型別而其實物件應該取另一種型別時,程式會自動進行型別轉換。型別所表示的值的範圍決定了轉換的過程 extern int i 宣告i int j 宣告並定義j extern double pi 3.1416 定義引用為物件起了另外乙個名字,引用是一種宣告...
c 伺服器開發之效能優化
為什麼要寫這篇文章?聊技術的時候,談到記憶體問題 cpu問題 效率問題的時候,無疑是考量乙個工程師的實戰水平,作為c 開發工程師,沒有自己解決以上問題的專業手段,或許就是缺陷。我之所以寫這個文章,主要是為了記錄 分享我的辦法。我之前寫過記憶體洩漏的一篇文章 其實也是一種手段,如果為你所用,聊技術的時...