Windows多執行緒程式設計(7) 原子操作

2021-06-20 03:59:05 字數 3987 閱讀 9311

今天介紹一種低層次的多執行緒同步機制--原子操作(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...