c++拾遺--多執行緒:原子操作解決執行緒衝突
在多執行緒中操作全域性變數一般都會引起執行緒衝突,為了解決執行緒衝突,引入原子操作。
#include #include #include #include int g_count = 0;
void count(void *p)
sleep(100); //do some work
}int main(void)
waitformultipleobjects(10, handles, 1, infinite);
printf("%d time g_count = %d\n", i, g_count);
//重置
g_count = 0;
} getchar();
return 0;
}
執行
理論上,g_count的最後結果應該是100,可事實卻並非如此,不但結果不一定是100,而且每次的結果還很可能不一樣。原因是,多個執行緒對同乙個全域性變數進行訪問時,特別是在進行修改操作,會引起衝突。詳細解釋:
設定斷點,檢視反彙編
g_count++;被分為三步操作:
1.把g_count的內容從記憶體中移動到暫存器eax
2.把暫存器eax加1
3.把暫存器eax中的內容移動到記憶體g_count的位址
三步以後,g_count的值被順利加1。
cpu執行的時間片內包含多條指令,每條指令執行期間不會被打斷,但如果乙個操作包含多條指令,則很有可能該操作會被打斷。g_count++;就是這樣的操作。
g_count被順利加到100的前提:每次加1,都建立在上一次加1順利完成的基礎上。也就是說,如果上一次加1被打斷,這一次的加1就得不到上一次加1的累積效果。自然,最後的結果,多半會小於100。
所謂原子操作,是指不會被執行緒排程機制打斷的操作,操作一旦開始,就得執行到結束為止。
原子操作可以是乙個步驟,也可以是多個操作步驟,但是其順序是不可以被打亂,或者切割掉只執行部分。原子操作一般靠底層彙編實現。
在標頭檔案winnt.h中提供了很多的原子操作函式,它們使用自加鎖的方式,保證操作的原子性,如自增操作
interlockedincrement,
函式原型
long cdecl_non_wvmpure interlockedincrement(
_inout_ _interlocked_operand_ long volatile *addend);
其它相關操作,請自行檢視標頭檔案。
使用該函式,我們修改執行緒函式count。修改很簡單,只需把g_count++改為interlockedincrement((long)&g_count);即可。
執行如下
顯然,在原子操作下,我們肯定是可以得到正確結果的。
本專欄目錄
所有內容的目錄
多執行緒拾遺 例題
原題 利用多執行緒迴圈列印a b c 思路一 printa printb printc 三個方法,對this加鎖,根據乙個flag來控制列印物件。public class abcre system.out.print a flag b notifyall public synchronized vo...
多執行緒設計拾遺
1 synchronized不能繼承,父類的方法是synchronized,那麼其子類過載方法中就不會繼承 同步 2 構造兩個執行緒之間實時通訊的方法分幾步 1 建立乙個pipedwriter和乙個pipedreader和它們之間的管道 pipedreader in new pipedreader ...
C 拾遺 多執行緒 C語言多執行緒的引入
c 拾遺 多執行緒 c語言多執行緒的引入 多執行緒是程式設計中的乙個重要內容。多核時代使多執行緒成為一種可能,顯然,一件事情多個人幹,效率一定會提公升。下面來看下c語言中是如何使用多執行緒的。先來看乙個例項 define crt secure no warnings include include ...