今天介紹一種低層次的多執行緒同步機制--原子操作(atomic operation)。原子操作保證同一時間只能有乙個執行緒對某個變數進行操作。通常一條c/c++語句對應多個彙編指令,而處理器的中斷可能發生在任意一條彙編指令處。因此,當乙個執行緒訪問某個變數時,可能會有另乙個執行緒也在訪問,這就造成了資料的不一致。
下面給出乙個例子。
#include #include dword winapi threadfunc(lpvoid p);
int num = 0;
int main(int argc, char **argv)
waitformultipleobjects(n, hthreadarray, true, infinite);
for (int i = 0; i < n; i++)
std::cout << "num = " << num << std::endl;
}return 0;}
dword winapi threadfunc(lpvoid p)
上面的程式每次啟動20個子執行緒,每個子執行緒對全域性變數num加1。模擬100次,程式執行結果並不總是20。這是因為threadfunc中的num++和num--操作不是原子操作,在執行的過程中發生了中斷。
下面是我的計算機的執行結果。
為了實現變數操作的同步,windows提供了一系列原子操作函式。下面詳細介紹這些函式。
1. interlockedincrement:指定的long型變數增加1
winbaseapi
long
winapi
interlockedincrement (
__inout long volatile *lpaddend
);
lpaddend:指向自增變數的指標。
返回值:返回自增後的值。
long定義在標頭檔案winnt.h中,如下所示。
#ifndef void
#define void void
typedef char char;
typedef short short;
typedef long long;
#if !defined(midl_pass)
typedef int int;
#endif
#endif
2. interlockeddecrement:指定的long型變數減少1
winbaseapi
long
winapi
interlockeddecrement (
__inout long volatile *lpaddend
);
lpaddend:指向自減變數的指標。
返回值:返回自減後的值。
3. interlockedexchange:對乙個long型變數賦值。
winbaseapi
long
winapi
interlockedexchange (
__inout long volatile *target,
__in long value
);
target
:指向賦值變數的指標。
value
:賦給target指向變數的值。
返回值
:返回未賦值之前target指向的變數的值。
當我們需要對指標賦值時,可以用interlockedexchangepointer函式。它其實是乙個基於interlockedexchange函式的巨集。這是因為對於32位程式,指標就是乙個long型的變數。
#define interlockedexchangepointer(target, value) \
(pvoid)interlockedexchange((plong)(target), (long)(value))
4. interlockedexchangeadd:對乙個long型變數做加法運算。
winbaseapi
long
winapi
interlockedexchangeadd (
__inout long volatile *addend,
__in long value
);
addend:指向long型變數的指標。
value:加數。執行後,*addend += value。
返回值:返回未做加法之前,addend指向的變數的值。
5. interlockedcompareexchange:比較賦值函式。
winbaseapi
long
winapi
interlockedcompareexchange (
__inout long volatile *destination,
__in long exchange,
__in long comperand
);
如果 *destination == comperand,*destination = exchange;否則,不執行任何操作。
返回值:*destination未修改之前的值。
對於高版本的windows,還定義了longlong型別的interlockedcompareexchange64函式,如下所示。
#if (_win32_winnt >= 0x0502)
winbaseapi
longlong
winapi
interlockedcompareexchange64 (
__inout longlong volatile *destination,
__in longlong exchange,
__in longlong comperand
);#endif
然後基於該函式,又定義了3個位運算函式(and,or,xor)和上述1~4個函式的longlong型別的版本。我們僅以and函式位列,列出**。
forceinline
longlong
interlockedand64 (
__inout longlong volatile *destination,
__in longlong value
)while (interlockedcompareexchange64(destination,
old & value,
old) != old);
return old;
}
最後,當我們使用c++語言的時候,windows對以上函式進行了過載,從而支援其它型別的變數。我們僅以interlockedincrement函式為例,列出在winbase.h檔案中的相關**。
#if defined(__cplusplus) /*
forceinline
unsigned long
interlockedincrement(
__inout __drv_interlocked unsigned long volatile *addend
)
原文: windows多執行緒程式設計之原子操作
volatile關鍵字 多個執行緒對同乙個變數進行讀寫操作時,需要原子操作,保證資料的正確性。常用的原子操作函式包括 返回變數執行增減操作之後的值 winbaseapi long winapi interlockedincrement inout long volatile lpaddend win...
Windows多執行緒程式設計
一 問題的提出 編寫乙個耗時的單執行緒程式 新建乙個基於對話方塊的應用程式singlethread,在主對話方塊idd singlethread dialog新增乙個按鈕,id為idc sleep six second,標題為 延時6秒 新增按鈕的響應函式,如下 void csinglethread...
windows多執行緒程式設計
程序 乙個執行的程式,記憶體,cpu時間等都歸程序所有.執行緒 cpu排程的最小單位,乙個程序內的多個執行緒共享4g記憶體.程式的乙個執行路徑 1.最基礎的使用方法.createthread,exitthread,closehand include include createthread,exit...