关键代码段也称为临界区,工作在用户方式下,它是指一个小代码段,在代码能执行前,它必须独占对某些资源的访问权。
通常把多线程中访问同一种资源的那部分代码当做关键代码段。
关键代码段就好像公共电话亭一样,只有公共电话亭没有人在打电话时,其他人才有可能去打电话,如果有人打电话,其他人必须等待,当使用电话的那个人离开后,其他人才可以进去打电话。关键代码段类似这种情况,只有没有线程访问关键代码段时,其他线程才可以访问关键代码段,否则必须等待才可以进入。
进入关键代码段之前,首先需要初始化一个这样的关键代码段,可以调用InitializeCriticalSection函数实现。
函数声明:
void InitializeCriticalSection( LPCRITICAL_SECTION lpCriticalSection );
lpCriticalSection Pointer to the critical section object.
该函数有一个参数,是一个指向LPCRITICAL_SECTION 结构体的指针。该函数式out类型,即作为返回值使用的。因此,在使用时,需要构造一个LPCRITICAL_SECTION 结构体类型的对象,然后将该对象的地址传递给该函数,系统自动维护该对象,我们不需要了解和访问该结构体的对象的内部成员。
如果想进入关键代码段,首先需要调用EnterCriticalSection函数,以获取指定的临界区对象的所有权。该函数等待指定的临界区对象的所有权,如果该所有权赋予了调用线程,则该函数就返回,否则该函数就会一直等待,从而导致线程等待。
void EnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection );
当调用线程获得了指定的临界区对象的所有权后,该线程就进入关键代码段,对所保护的资源进行访问。
线程使用完所保护的资源之后,需要调用LeaveCriticalSection函数,释放指定的临界区对象的所有权,之后,其他想要获得该临界区的对象所有权的线程就可以获得该所有权,从而进入关键代码段。访问保护的资源。
void LeaveCriticalSection( LPCRITICAL_SECTION lpCriticalSection );
对临界区对象来说,当不再需要时,需要调用DeleteCriticalSection函数释放该对象,该函数将释放一个没有被任何线程所拥有的临界区对象的所有资源。
void DeleteCriticalSection( LPCRITICAL_SECTION lpCriticalSection );
利用关键代码段实现线程同步需要调用以上四个函数,以及调用步揍。
#include <windows.h>//调用windows API 函数
#include <iostream.h>
//关键代码段实现线程同步
int tickets=10;
CRITICAL_SECTION CriticalSection ; //关键代码段
//线程1函数
DWORD WINAPI Fun1Proc( LPVOID lpParameter )
{
while( true )
{
EnterCriticalSection( &CriticalSection );
if( tickets > 0 )
{
Sleep(1);
cout << "线程1卖出一张票." << tickets-- << endl;
LeaveCriticalSection( &CriticalSection );
}
else
{
LeaveCriticalSection( &CriticalSection );
break;
}
}
return 0;
}
//线程2函数
DWORD WINAPI Fun2Proc( LPVOID lpParameter )
{
while( true )
{
EnterCriticalSection( &CriticalSection );
if( tickets > 0 )
{
Sleep(1);
cout << "线程2卖出一张票." << tickets-- << endl;
LeaveCriticalSection( &CriticalSection );
}
else
{
LeaveCriticalSection( &CriticalSection );
break;
}
}
return 0;
}
//main函数是主线程入口函数,然后可以创建其他新线程
void main()
{
HANDLE hThread1;
HANDLE hThread2;
//创建两个线程
hThread1 = CreateThread( NULL, 0, Fun1Proc, NULL, 0, NULL );
hThread2 = CreateThread( NULL, 0, Fun2Proc, NULL, 0, NULL );
CloseHandle( hThread1 );
CloseHandle( hThread2 );
InitializeCriticalSection( &CriticalSection );
Sleep(400);
cout << "over." << endl;
DeleteCriticalSection( &CriticalSection );
}