C++服務器開發之筆記三

爲何須要原子性操做?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 聲明的變量的值的時候,系統老是從新從它所在的內存讀取數據,而不是使用保存在寄存器中的備份。即便它前面的指令剛剛從該處讀取過數據。並且讀取的數據馬上被保存

相關文章
相關標籤/搜索