Interlocked系列函數用來保證原子訪問。
InterlockedExchangeAdd提供保證long類型的原子操作。
InterlockedExchangeAdd64提供long long 64位的原子操作。
搞不懂為什么不提供int類型的,int類型轉換成long類型就是2個不同內存地址的變量,
再來對long類型進行原子操作也就沒用了?
(這里請教了下c++網友,說是vs2010對類型檢查很嚴格,可能之前的編譯器也許會放松點?)
int類型要進行原子操作只能強轉為long指針了
static int l=0;
unsigned __stdcall ThreadFun(void* par)
{
//注意這里的強轉,不會改變內存地址導致原子操作無效
InterlockedExchangeAdd((long*)&l,1);
return 0;
}
#include <iostream> #include <process.h> #include <windows.h> using namespace std; static long l=0; unsigned __stdcall ThreadFun(void* par) { InterlockedExchangeAdd(&l,1); return 0; } int main() { HANDLE hThread[2]; hThread[0]=(HANDLE)_beginthreadex(NULL,0,&ThreadFun,NULL,0,NULL); hThread[1]=(HANDLE)_beginthreadex(NULL,0,&ThreadFun,NULL,0,NULL); //等待所有線程結束 WaitForMultipleObjects(2,hThread,true,INFINITE); CloseHandle(hThread[0]); CloseHandle(hThread[1]); //就算沒有進行原子操作,測試的時候基本上還是輸出2,極少輸出1,變量++是秒殺完成的。 //在實際項目的大並發情況下那么結果是1就很容易出現 cout<<"l="<<l<<endl; system("PAUSE"); return 0; }
上面幾個函數返回由加數指向的變量的初始值,
long i=0;
cout<<InterlockedExchangeAdd(&i,1)<<endl;//輸出0
cout<<InterlockedExchangeAdd(&i,1)<<endl;//輸出1
書上提到Interlocked速度很快,這點不錯,C#中經常用相應的函數,而且不需要在用戶模型和內核模式之前切換
另外提到的一個重要點,原子操作的變量必須是內存對齊的。
上面的是對變量進行原子增加,下面的幾個函數是講參數變為指定的值(原子操作)。
InterlockedExchange
InterlockedExchange64
InterlockedExchangePointer//如果應用程序是32位,那么這里替換的就是32位,64位程序則對應
用InterlockedExchange實現旋轉鎖
#include <iostream> #include <process.h> #include <windows.h> using namespace std; BOOL b=FALSE; unsigned __stdcall ThreadFun(void* par) { int* pout=(int*)par; while(InterlockedExchange((unsigned long*)&b,TRUE)==TRUE) { Sleep(500); } for(int i=0;i<3;i++) { Sleep(1000); cout<<*pout<<endl; } InterlockedExchange((unsigned long*)&b,FALSE); return 0; } int main() { HANDLE hThread[2]; int a1=1; int a2=2; hThread[0]=(HANDLE)_beginthreadex(NULL,0,&ThreadFun,&a1,0,NULL); hThread[1]=(HANDLE)_beginthreadex(NULL,0,&ThreadFun,&a2,0,NULL); //等待所有線程結束 WaitForMultipleObjects(2,hThread,true,INFINITE); CloseHandle(hThread[0]); CloseHandle(hThread[1]); system("PAUSE"); return 0; }
windows核心編程提到,旋轉鎖很費cpu,這里把Sleep時間設置長點就不浪費了吧,但是卻不能及時搶到資源所有權。
旋轉鎖貌似就是實現了對代碼塊的鎖定,假如我們沒有使用c#中lock等鎖定代碼塊的,或者也沒用底層的CRITICAL_SECTION,那么要鎖定代碼塊貌似我知道的就旋轉鎖。
Interlocked系列函數還剩下下面2個,功能是以原子操作方式進行對比和設置。具體查詢msdn。
InterlockedCompareExchange
InterlockedCompareExchangePointer
本文版權歸kennyMc和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。