除了使用臨界區與互斥可以完成線程間的同步外,還可以使用信號量CSemaphore。使用信號量還有一個好處便是:信號允許多個線程同時使用共享資源,這便與操作系統中的PV操作有些雷同的地方。它指出了同時訪問共享資源的線程最大數目。
在信號量內部有一個計數器,當有線程訪問共享資源時,計數器將自動遞減,當它為0時,不再允許其他線程對共享資源的訪問,直到有一個線程釋放共享資源,從而完成對共享資源的保護。
在建立一個信號量時必須提供一個初始化值和一個最大計數值,如:
CSemaphore Semaphore(2,2);
可以在類的構造函數中動態地創建CSemaphore對象,如:
Semaphore=new CSemaphore(2,2);
信號量CSemaphore被建立後,就可以准備用它來對共享資源進行訪問計數。要完成計數處理,首先應建立一個CSingleLock或CMultiLock對象,如:
CSingleLock SingleLock(Semaphore);
要減小這個信號Semaphore的計數值,只須調用CSingleLock對象的成員函數Lock()即可:
SingleLock.Lock();
同樣,通過調用UnLock()來釋放這個信號量,即:
SingleLock.UnLock();
從而我們可這樣來申明類:
#include "afxmt.h"
class CSharedResource
{
private:
CSemaphore* ptrSemaphore;
public:
CSharedResource();
~CSharedResource();
void AccessResource();
};
在構造函數中完成對信號對象的創建:
CSharedResource::CSharedResource()
{
ptrSemaphore=new CSemaphore(2,2);
}
在析構函數中完成對信號對象的釋放:
CSharedResource::~CSharedResource()
{
delete ptrSemaphore;
}
用以下過程來訪問共享資源:
void CSharedResource::AccessResource()
{
CSingleLock SingleLock(ptrSemaphore);
SingleLock.Lock();
/* ......
資源訪問
*/
Sleep(1000);
}
再建立使用信號量的線程函數:
UINT Thread_Proc1(LPVOID param)
{
SharedResource.AccessResource();
::MessageBox((HWND)param,"Thread #1 had accessed the Semaphore!","Thread Proc1",MB_OK);
return 0;
}
UINT Thread_Proc2(LPVOID param)
{
SharedResource.AccessResource();
::MessageBox((HWND)param,"Thread #2 had accessed the Semaphore!","Thread Proc2",MB_OK);
return 0;
}
UINT Thread_Proc3(LPVOID param)
{
SharedResource.AccessResource();
::MessageBox((HWND)param,"Thread #3 had accessed the Semaphore!","Thread Proc3",MB_OK);
return 0;
}
再用以下代碼執行各個線程函數:
HWND hWnd=GetSafeHwnd();
AfxBeginThread(Thread_Proc1,hWnd);
AfxBeginThread(Thread_Proc2,hWnd);
AfxBeginThread(Thread_Proc3,hWnd);
這樣當Thread_Proc1和Thread_Proc2占用信號量之後,只有等其中一個釋放信號量之後,Thread_Proc3方可占用信號量,達到了線程之間資源的保護,實現數據共享!
本文即本人在學習多任務多線程過程的手記,供大家參考,望能得到各位指點。
本文配套源碼