C 拾遺 多執行緒 原子操作解決執行緒衝突

2021-06-28 20:07:28 字數 1633 閱讀 5900

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 ...