1. 程式人生 > >Windows下的多執行緒

Windows下的多執行緒

Windows下多執行緒的同步與互斥

critical section

#include<stdio.h>#include<process.h>#include<windows.h>// Usage// EnterCriticalSection(CRITICAL_SECTION)// ...//do some thing// LeaveCriticalSection(CRITICAL_SECTION)longglobal;unsignedint __stdcall ThreadFunction(void*handle);constint THREAD_NUM =10;//if the number is more than 100,there will be a question
// definition of critical section CRITICAL_SECTION g_csThreadCode;int main(){// initialize critical sectionInitializeCriticalSection(&g_csThreadCode); HANDLE handle[THREAD_NUM];global=0;int i =0;while(i < THREAD_NUM){ handle[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFunction,&i,0, NULL);
++i;}WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);//wait for all threads to finish the taskDeleteCriticalSection(&g_csThreadCode);return0;}unsignedint __stdcall ThreadFunction(void*handle){EnterCriticalSection(&g_csThreadCode);// enter critical sectionglobal++;Sleep(0);//重新發起一次CPU競爭 printf
("global variable is %d\n",global);LeaveCriticalSection(&g_csThreadCode);return0;}

這個例子當執行緒數設定為150時,我的主機就無法正常全部列印了

mutex

// 互斥量Mutex:// Usage// WaitForSingleObject(hMutex,…);  // ...//do something  // ReleaseMutex(hMutex);  #include<stdio.h>#include<process.h>#include<windows.h>longglobal;unsignedint __stdcall ThreadFunction(void*handle);constint THREAD_NUM =10;// 互斥量
HANDLE hmutex;int main(){// 初始化互斥量,第二個引數為TRUE表示互斥量為建立程序所有
    hmutex =CreateMutex(NULL, FALSE, NULL);

    HANDLE handle[THREAD_NUM];global=0;int i =0;while(i < THREAD_NUM){
        handle[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFunction,&i,0, NULL);
        i++;}WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);// 銷燬互斥量CloseHandle(hmutex);return0;}unsignedint __stdcall ThreadFunction(void*handle){WaitForSingleObject(hmutex, INFINITE);// 等待互斥量被觸發global++;Sleep(0);
    printf("global variable is %d\n",global);ReleaseMutex(hmutex);// 觸發互斥量return0;}

互斥量和關鍵段的區別互斥量可以設定等待時間

event

// Usage// SetEvent(hEvent);// WaitForSingleObject(hEvent,…);// 等待其他程序的setevent,然後執行操作#include<stdio.h>#include<process.h>#include<windows.h>longglobal;unsignedint __stdcall ThreadFunction(void*handle);constint THREAD_NUM =10;//事件
HANDLE hevent;int main(){//初始化事件初
    hevent =CreateEvent(NULL, FALSE, FALSE, NULL);
    HANDLE  handle[THREAD_NUM];global=0;int i =0;SetEvent(hevent);//如果這一行註釋,則事件沒有觸發,所有執行緒等待while(i < THREAD_NUM){  
        handle[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFunction,&i,0, NULL);  
        i++;}WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);//銷燬事件CloseHandle(hevent);return0;}unsignedint __stdcall ThreadFunction(void*handle){WaitForSingleObject(hevent,INFINITE);global++;Sleep(0);
    printf("global variable is %d\n",global);SetEvent(hevent);//觸發事件 return0;}

事件更適合一個執行緒像另一個執行緒傳送通知訊息

semaphore

// WaitForSingleObject(hsemaphore,INFINITE);// ...//do something// ReleaseSemaphore(hsemaphore, 1, NULL);#include<stdio.h>#include<process.h>#include<windows.h>longglobal;unsignedint __stdcall ThreadFunction(void*handle);constint THREAD_NUM =10;// 訊號量
HANDLE hsemaphore;int main(){// 初始化訊號量和關鍵段
    hsemaphore =CreateSemaphore(NULL,0,1, NULL);// 當前0個資源,最大允許1個同時訪問ReleaseSemaphore(hsemaphore,1, NULL);// 訊號量++,多出一個資源,如果註釋掉,所有執行緒等待
    HANDLE handle[THREAD_NUM];global=0;int i =0;while(i < THREAD_NUM){
        handle[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFunction,&i,0, NULL);++i;}WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);// 銷燬訊號量CloseHandle(hsemaphore);return0;}unsignedint __stdcall ThreadFunction(void*handle){WaitForSingleObject(hsemaphore,INFINITE);global++;Sleep(0);
    printf("global variable is %d\n",global);ReleaseSemaphore(hsemaphore,1, NULL);// 訊號量++return0;}

semaphore針對資源而言,對於一個區間允許有多個執行緒訪問

以上幾種方法的對比

critical section mutex event semaphore
非核心 核心 核心 核心
只能同步單個程序的執行緒 屬於PV操作
可以由軟體層面忙等來實現 互斥量是可以命名的,也就是說它可以跨越程序使用 主要用於訊息通知等 允許多個執行緒在同一時刻訪問同一資源,但是需要限制在同一時刻訪問此資源的最大執行緒數目

程序互斥的軟體解決方法

  • Use two shared data items
int turn;//指示該誰進入臨界區  bool flag[];//指示程序是否準備好進入臨界區
  • code for enter critical section
flag[i]= TRUE;
turn = j;while(flag[j]&&turn==j);
  • code for exit critical section
flag[j]=FALSE;

其他基於硬體的原子操作