windows 核心編程之8 使用者模式下的線程同步

來源:互聯網
上載者:User
使用者模式下的線程同步有下面2種情況,需要用到線程同步1 需要讓多個線程同時訪問一個資源,同時不能破壞資源的完整性2 一個線程需要通知另外一個線程,任務完成。1 原子訪問方式:提供下面以下的原子方式訪問的函數:
#include <Windows.h>#include <stdio.h>int main(){// 原子方式操作LONG volatile ivVariable = 10;LONGLONG volatile llVariable = 10;// return initial value of first parameter// you can use it to do subtraction, first parameter negativeLONG ltestVar = InterlockedExchangeAdd(&ivVariable, 1);LONGLONG llTestVariable = InterlockedExchangeAdd64(&llVariable, 2);//BOOL volatile bTest = FALSE;BOOL bOldValue = (BOOL)InterlockedExchange((LONG volatile*)&bTest, TRUE);volatile int*p = new int(10);LONG* lptest = new LONG(100);LONG* plvalue = (LONG*)InterlockedExchangePointer(&p,lptest);delete p;delete lptest;LONG volatile lvolatileCompateValue = 10;// function 參數1與參數3是否相等,不相等不執行操作,//相等時,把參數2賦值給參數1,傳回值參數1以前的值LONG lOldValue = InterlockedCompareExchange(&lvolatileCompateValue, 15, 11);// 參數1 是一個指標LONG volatile* lpvolatile = new LONG(11);LONG* lp = new LONG(11);LONG* lOldCompateValue =(LONG*) InterlockedCompareExchangePointer((volatile PVOID*)&lpvolatile,(PVOID)lp,(PVOID)lpvolatile);return 0;}
下面是原子訪問的鏈表棧
#include <Windows.h>#include <stdio.h>#include <tchar.h>// 原子方式訪問單向鏈表typedef struct mydata{int i;TCHAR ch[10];double dou;}LISTDATA;typedef struct _Slist_item{SLIST_ENTRY m_entry;LISTDATA m_data;}LISTTIME,*PLISTTIME;int main(){SLIST_HEADER head;SLIST_ENTRY slistEntry;LISTTIME ltem;PLISTTIME pLitem = NULL;InitializeSListHead(&head);for (int i = 0; i< 10; i++){pLitem = new LISTTIME;pLitem->m_data.i = i;pLitem->m_data.dou = 100;_tcscpy_s(pLitem->m_data.ch,10,TEXT("asdf"));InterlockedPushEntrySList( &head, &pLitem->m_entry );}LONG lSize = QueryDepthSList(&head);for (int i = 0; i < 10; ++i){pLitem = (PLISTTIME)InterlockedPopEntrySList(&head);delete pLitem;}InterlockedFlushSList(&head);return 0;}
2 快取行Windows SDK 代碼最後釋放記憶體有錯,buffer指標移動了,下面的代碼,已經改好,增加了一些新資訊
#include <windows.h>#include <malloc.h>    #include <stdio.h>#include <tchar.h>typedef BOOL (WINAPI *LPFN_GLPI)( PSYSTEM_LOGICAL_PROCESSOR_INFORMATION,  PDWORD);int _cdecl _tmain (){BOOL done;BOOL rc;DWORD returnLength;DWORD procCoreCount;DWORD byteOffset;PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer, FreeBuffer;LPFN_GLPI Glpi;Glpi = (LPFN_GLPI) GetProcAddress(GetModuleHandle(TEXT("kernel32")),"GetLogicalProcessorInformation");if (NULL == Glpi) {_tprintf(TEXT("GetLogicalProcessorInformation is not supported.\n"));return (1);}done = FALSE;buffer = NULL;returnLength = 0;while (!done) {rc = Glpi(buffer, &returnLength);if (FALSE == rc) {if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {if (buffer) free(buffer);FreeBuffer = buffer=(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(returnLength);if (NULL == buffer) {_tprintf(TEXT("Allocation failure\n"));return (2);}} else {_tprintf(TEXT("Error %d\n"), GetLastError());return (3);}} else done = TRUE;}procCoreCount = 0;byteOffset = 0;while (byteOffset < returnLength) {switch (buffer->Relationship) {case RelationProcessorCore:procCoreCount++;break;case RelationNumaNode:printf("節點資訊:\n");printf("numaNode = %d\n",buffer->NumaNode.NodeNumber);break;case RelationCache:printf("CPU 高速緩衝區\n");printf("關聯性 %d\n",buffer->Cache.Associativity);printf("Cache %d 緩衝\n",buffer->Cache.Level);printf("Cache %d 緩衝行\n",buffer->Cache.LineSize );printf("Cache %dKB 大小\n", buffer->Cache.Size / 1024);switch(buffer->Cache.Type){case CacheData:printf("CacheData\n");break;case CacheInstruction:printf("CacheInstruction\n");break;case CacheTrace:printf("CacheTrace\n");break;case CacheUnified:printf("CacheUnified\n");break;}break;case RelationProcessorPackage:printf("RelationProcessorPackage:\n");break;default:break;}byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);buffer++;printf("=========================================================\n");}_tprintf(TEXT("Number of active processor cores: %d\n"), procCoreCount);free (FreeBuffer);return 0;}
3 進階線程同步不要使用旋轉鎖的方式來,線程之間同步4 關鍵段CRITICAL_SECTION     是關鍵段的結構體,我們不需要瞭解結構體的細節,協助文檔也沒有它的說明.下面是初始化關鍵段得函數,參數是結構體地址InitializeCriticalSection(&cs);DeleteCriticalSection(&cs); 這個函數是刪除,關鍵段結構體,必須成對使用,否則資源流失EnterCriticalSection(&cs);
//需要保護的資源
LeaveCriticalSection(&cs);也必須要成對使用可以使用 TryEnterCriticalSection 來替換 EnterCriticalSection  這個函數會嘗試請求資源,如果沒有資源,返回false,有資源返回true,同時會更新關鍵段結構體,所以訪問了資源後,可以調用 LeaveCriticalSection。 下面的代碼說明情況了。if(TryEnterCriticalSection(&cs))
{
//需要保護的資源

LeaveCriticalSection(&cs);
}
else
{
//沒有資源可以訪問
//不需要調用 LeaveCriticalSection;
}下面的代碼介紹了怎麼使用關鍵段

#include <Windows.h>#include <stdio.h>#include <tchar.h>#include <process.h>class MyCriticalSection{public:MyCriticalSection(){InitializeCriticalSection(&m_cs);}~MyCriticalSection(){DeleteCriticalSection(&m_cs);}void Lock(){EnterCriticalSection(&m_cs);}void UnLock(){LeaveCriticalSection(&m_cs);}BOOL TryLock(){return TryEnterCriticalSection(&m_cs);}void TryUnLock(){UnLock();}private:CRITICAL_SECTION m_cs;};int gSum = 0;MyCriticalSection criticalsection;unsigned int WINAPI ThreadFuncOne(LPVOID lparam){criticalsection.Lock();for (int i = 0; i < 100; ++i){gSum++;}criticalsection.UnLock();return 0;}unsigned int WINAPI ThreadFuncTwo(LPVOID lparam){criticalsection.Lock();for (int i = 0; i < 100; ++i){gSum++;Sleep(10);}criticalsection.UnLock();return 0;}unsigned int WINAPI ThreadFuncThree(LPVOID lparam){while(!criticalsection.TryLock()){printf("沒有資源可以使用\n");Sleep(10);}printf("資源可以使用\n");for (int i = 0; i < 100; ++i){gSum++;}criticalsection.TryUnLock();return 0;}int main(int argc, char **argv){HANDLE hThread1 = (HANDLE)_beginthreadex(NULL, 0, ThreadFuncOne, NULL, 0, NULL);HANDLE hThread2 = (HANDLE)_beginthreadex(NULL, 0, ThreadFuncTwo, NULL, 0, NULL);HANDLE hThread3 = (HANDLE)_beginthreadex(NULL, 0, ThreadFuncThree, NULL, 0, NULL);HANDLE harray[3] = {hThread1,hThread2,hThread3};WaitForMultipleObjects(_countof(harray),harray,TRUE,INFINITE);printf("sum = %d\n", gSum);system("pause");return 0;}
初始化的時候可以使用//初始化的時候,使用旋轉鎖 單CPU上沒有作用

WINBASEAPI
BOOL
WINAPI
InitializeCriticalSectionAndSpinCount(
    __out LPCRITICAL_SECTION lpCriticalSection,
    __in  DWORD dwSpinCount
    );

SetCriticalSectionSpinCount 設定旋轉鎖的次數,單CPU沒有效果,這個函數是沒有使用上面那個函數,初始化關鍵段,在後期使用中,可以使用下面這個函數,來改變!
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.