关键代码段,也称为临界区
,工作在用户方式下。它是指一个小代码段
,在代码能够执行前,它必须独占对某些资源的访问权
。通常把多线程中访问同一种资源的那部分代码当做关键代码段。
1. 初始化关键代码段
调用InitializeCriticalSection函数初始化一个关键代码段。
InitializeCriticalSection(
_Out_ LPCRITICAL_SECTION lpCriticalSection
);
该函数只有一个指向CRITICAL_SECTION结构体的指针。在调用InitializeCriticalSection函数之前,首先需要构造一个CRITICAL_SCTION结构体类型的对象,然后将该对象的地址传递给InitializeCriticalSection函数。
2进入关键代码段
VOID
WINAPI
EnterCriticalSection(
_Inout_ LPCRITICAL_SECTION lpCriticalSection
);
调用EnterCriticalSection函数,以获得指定的临界区对象的所有权,该函数等待指定的临界区对象的所有权,如果该所有权赋予了调用线程,则该函数就返回;否则该函数会一直等待,从而导致线程等待。
3.退出关键代码段
VOID
WINAPI
LeaveCriticalSection(
_Inout_ LPCRITICAL_SECTION lpCriticalSection);
线程使用完临界区所保护的资源之后,需要调用LeaveCriticalSection函数,释放指定的临界区对象的所有权。之后,其他想要获得该临界区对象所有权的线程就可以获得该所有权,从而进入关键代码段,访问保护的资源。
4.删除临界区
WINBASEAPI
VOID
WINAPI
DeleteCriticalSection(
_Inout_ LPCRITICAL_SECTION lpCriticalSection
);
当临界区不再需要时,可以调用DeleteCriticalSection函数释放该对象,该函数将释放一个没有被任何线程所拥有的临界区对象的所有资源。
BOOL COneIPCChannel::InitIPCChannel(CWnd * pVideoWnd)
{
m_pVideoBuffer = new CVideoRecieveBuffer;
m_pVideoWnd = pVideoWnd;
m_bPlaying = FALSE;
m_isTFPlay=FALSE;
InitializeCriticalSection(&m_cs);
m_hWaitEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
return TRUE;
}
BOOL COneIPCChannel::InitIPCChannelREMOTE(CWnd * pVideoWnd,int *Session)
{
m_Session=Session;
m_pVideoWnd = pVideoWnd;
m_bPlaying = FALSE;
m_isTFPlay = FALSE;
m_pVideoBuffer = new CVideoRecieveBuffer;
InitializeCriticalSection(&m_cs);
m_hWaitEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
return TRUE;
}
卖票系统
#include <stdio.h>
#include <windows.h>
#include <process.h>
int iTickets = 5000;
CRITICAL_SECTION g_cs;
// A窗口 B窗口
DWORD WINAPI SellTicketA(void* lpParam)
{
while (1)
{
EnterCriticalSection(&g_cs);//进入临界区
if (iTickets > 0)
{
Sleep(1);
iTickets--;
printf("A remain %d\n", iTickets);
LeaveCriticalSection(&g_cs);//离开临界区
}
else
{
LeaveCriticalSection(&g_cs);//离开临界区
break;
}
}
return 0;
}
DWORD WINAPI SellTicketB(void* lpParam)
{
while (1)
{
EnterCriticalSection(&g_cs);//进入临界区
if (iTickets > 0)
{
Sleep(1);
iTickets--;
printf("B remain %d\n", iTickets);
LeaveCriticalSection(&g_cs);//离开临界区
}
else
{
LeaveCriticalSection(&g_cs);//离开临界区
break;
}
}
return 0;
}
int main()
{
HANDLE hThreadA, hThreadB;
hThreadA = CreateThread(NULL, 0, SellTicketA, NULL, 0, NULL); //2
hThreadB = CreateThread(NULL, 0, SellTicketB, NULL, 0, NULL); //2
CloseHandle(hThreadA); //1
CloseHandle(hThreadB); //1
InitializeCriticalSection(&g_cs); //初始化关键代码段
Sleep(40000);
DeleteCriticalSection(&g_cs);//删除临界区
system("pause");
return 0;
}