一、有關函數:
InitializeCriticalSection() 創建一個臨界段
DeleteCriticalSection() 釋放一個臨界段
EnterCriticalSection() 獲取對臨界段的所有權,獨佔共享資源
TryEnterCriticalSection() 試圖獲得對臨界段的所有權,但不阻塞
LeaveCriticalSection() 釋放對資源的所有權
二、舉例
1,
#include<windows.h>
#include<process.h>
#include<stdio.h>
CRITICAL_SECTION cs;
int a[5];
void Thread(void* pParams)
{
int i,num=0;
while(1)
{
EnterCriticalSection(&cs);//試圖獲得臨界段對象
for(i=0;i<5;i++)
a[i]=num;
num++;
LeaveCriticalSection(&cs);//釋放對臨界段對象的所有權
}
}
int main(void)
{
InitializeCriticalSection(&cs);//初始化臨界段對象
_beginthread(Thread,0,NULL);
while(1)
{
EnterCriticalSection(&cs);
printf("%d %d %d %d %d/n",a[0],a[1],a[2],a[3],a[4]);
LeaveCriticalSection(&cs);
}
return 0;
}
以上黑色部分是沒利用臨界段的,可想而知,結果是無法預知的。加了紅色部分之後,就可以有規律的輸出了,因爲賦值和輸出的順序得到了妥善安排,而不會亂佔亂用。
臨界段,就猶如領導,若沒得到領導的允許,就不允許行動;若領導禁止了,就必須停止行動。
2、關於銀行中客戶獲取ID 問題
#include<windows.h>
#include<process.h>
#include<iostream.h>
CRITICAL_SECTION cs;
unsigned int currentID=1;
unsigned long _stdcall MyThread(LPVOID pParam)
{
int id;
EnterCriticalSection(&cs);
id = currentID;
Sleep(0);//將本時間片的NGCHU剩餘時間讓出。爲了把不同步效果明顯表現出來,現實中不用Sleep
currentID++;
LeaveCriticalSection(&cs);
cout<<"My Idntifier is:"<<id<<endl;
return id;
}
int main(int argc,char *argv[])
{
HANDLE handle;
DWORD dw;//保存新線程的id
InitializeCriticalSection(&cs);
for(int i=0;i<100;i++)
{
handle = CreateThread(NULL,0,MyThread,NULL,0,&dw);
CloseHandle(handle);
}
Sleep(6000);
return 0;
}
以上,若沒有加上紅色部分,輸出會十分混亂,導致很多人都擁有了相同的ID號。加上了之後,就能夠有條不紊的按照獲得的ID號進行輸出。
三、比較:
第一個例子是創建了一個線程,然後讓其自行運行,只要把輸入輸出按順序就行。
第二個例子是按照每次需要,每次都創建線程,可以人工控制輸入輸出,然後也依然是按順序來。
另外:
我們發現上面用了兩個不一樣的創建線程的函數:_beginthread 和 CreateThread
1、_beginthread是c++的函數 ,CreateThread是windows API函數
2、_beginthread只是簡單的去執行線程,而CreateThread是通過句柄去執行線程,執行結束要要記得關閉句柄