爲何須要原子性操做?html
咱們考慮一個例子:
(1)x++這個常見的運算符在內存中是怎樣操做的?
從內存中讀x的值到寄存器中,對寄存器加1,再把新值寫回x所處的內存地址shell
如果有兩個線程同時對同一個變量++,就會出現問題,以下:服務器
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,緣由就是否是原子操做,解決方法有兩個:性能
一 加鎖,但鎖競爭是高性能服務器的殺手,因此這裏不能用。fetch
二 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
無鎖隊列實現
http://coolshell.cn/articles/8239.html線程
服務器開發中,volatile常常用到:htm
volatile的做用: 做爲指令關鍵字,確保本條指令不會因編譯器的優化而省略,且要求每次直接讀值。簡單地說就是防止編譯器對代碼進行優化blog
當要求使用volatile 聲明的變量的值的時候,系統老是從新從它所在的內存讀取數據,而不是使用保存在寄存器中的備份。即便它前面的指令剛剛從該處讀取過數據。並且讀取的數據馬上被保存